这里介绍一个包装器方法:该方法接收一个参数,这个参数是一个返回值为
说一下背景:不说是什么原因了,至少现状是这样的,项目中会出现多个位置几乎同时调用同一个方法的场景,这个方法会发
针对上面的情况,首先想到的就是创建一个类,其中有一个方法用来包装目标方法,在弄个变量存储Promise的状态……
项目中使用的是
function PromiseFnWrapper(fn) { this.isEnd = true; this.list = []; this.fn = fn; } PromiseFnWrapper.prototype.resolveHandler = function (data) { if (this.list.length) { this.list.forEach(function (deferred) { deferred.resolve(data); }); } this.list.length = 0; this.isEnd = true; } PromiseFnWrapper.prototype.rejectHandler = function (errorData) { if (this.list.length) { this.list.forEach(function (deferred) { deferred.reject(errorData); }); } this.list.length = 0; this.isEnd = true; } PromiseFnWrapper.prototype.exec = function () { var deferred = $q.defer(); this.list.push(deferred); if (this.isEnd) { this.isEnd = false; this.fn.apply(null, arguments).then(this.resolveHandler.bind(this), this.rejectHandler.bind(this)); } return deferred.promise; }
上一版中没有将
class PromiseFnWrapper { isEnd = true; list = []; constructor(fn, thisArg) { this.fn = fn; this.thisArg = thisArg; } exec() { let arg = arguments; return new Promise((resolve, reject) => { this.list.push({ resolve, reject }); if (this.isEnd) { this.isEnd = false; this.fn.apply(this.thisArg, arg).then((data) => { if (!this.list.length) return; this.list.forEach((deferred) => { deferred.resolve(data); }); }, (errordata) => { if (!this.list.length) return; this.list.forEach((deferred) => { deferred.reject(errordata); }); }).finally(() => { this.list.length = 0; this.isEnd = true; }); } }); } }
采用类的方式确实解决了所说的问题,但是未免有点太富态了,下面就精简一下
function createPromiseFnWrapper(fn, thisArg) { let promise = null; return function () { let args = arguments; if (promise == null) { promise = new Promise((resolve, reject) => { fn.apply(thisArg, args).then((data) => { resolve(data); }).catch((errorData) => { reject(errorData); }).finally(() => { promise = null; }); }); } return promise; }; }
这种方式和上面闭包方式的代码量差不多。
function createPromiseFnWrapper(fn) { let promise = null; return new Proxy(fn, { apply(target, thisArg, args) { if (promise == null) { promise = new Promise((resolve, reject) => { target.apply(thisArg, args).then((data) => { resolve(data); }).catch((errorData) => { reject(errorData); }).finally(() => { promise = null; }); }); } return promise; } }); }
代码量差不多,是真的差不多……你有什么优势,为什么选择你……我开始不知道,不过在这里发现了一个点眉目,请看移步:Proxy 和 Reflect。说一点:这种方式包装之后,