这里介绍一个包装器方法:该方法接收一个参数,这个参数是一个返回值为
说一下背景:不说是什么原因了,至少现状是这样的,项目中会出现多个位置几乎同时调用同一个方法的场景,这个方法会发
针对上面的情况,首先想到的就是创建一个类,其中有一个方法用来包装目标方法,在弄个变量存储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。说一点:这种方式包装之后,