我正在尝试编写一个 Promise Polyfill 以更好地理解 Promise。 我在网上搜索了一下,找到了一段我能在一定程度上理解的代码。
function CustomPromise(executor) {
var state=PENDING;
var value = null;
var handlers=[];
var catchers = [];
function resolve(result) {
if(state!==PENDING) return;
state=FULFILLED;
value = result;
handlers.forEach((h)=>h(value)); //this line
}
function reject(error) {
if(state!==PENDING)return;
state=REJECTED;
value=error;
catchers.forEach(c=>c(value)); // this line
}
this.then = function(successCallback) {
if(state === FULFILLED) {
successCallback(value);
}else {
handlers.push(successCallback);
}
return this;
}
this.catch = function(failureCallback) {
if(state===REJECTED){
failureCallback(value)
} else {
catchers.push(value);
}
}
executor(resolve,reject);
}
即使这样我也无法理解处理程序和捕手的使用。据说,它们是为了应对承诺没有兑现或被拒绝的情况。解释这两行也会有所帮助。 现在,上述实现的实际问题是它在像
let p1 = Promise.resolve("Hello World");
这样使用时不起作用。我尝试将其转换为基于类的,但我无法做到这一点。
我的尝试:
class CustomPromise {
constructor(callback){
this.state = PENDING;
this.executor = callback;
this.value = null;
this.handlers = [];
this.catchers = [];
this.then = function(successCallback) {
if(this.state === FULFILLED) {
successCallback(this.value);
}else {
this.handlers.push(successCallback);
}
return this;
};
this.catch = function(failureCallback) {
if(this.state===REJECTED){
failureCallback(this.value)
} else {
this.catchers.push(this.value);
}
};
}
static resolve(result) {
if(this.state!==PENDING) return;
this.state=FULFILLED;
this.value = result;
this.handlers.forEach((h)=>h(this.value));
// return new CustomPromise( function ( fulfil ) {
// fulfil( value );
// });
}
static reject(error) {
if(this.state!==PENDING)return;
this.state=REJECTED;
this.value=error;
this.catchers.forEach(c=>c(this.value));
}
// executor(resolve,reject);
}
有人可以更正功能方法,使其适用于
CustomPromise.resolve()
场景,或者对我基于类的方法进行更正也将不胜感激。
编辑:尝试过CustomPromise.prototype.resolve = function(error) {...}
仍然出现同样的错误CustomPromise.resolve is not a function
EDIT2:在基于类的方法中,我无法实现 executor 回调。我只希望其中一种方法适用于像 Promise.resolve()
这样的情况
要扩展
CustomPromise
的第一个(工作)版本,请在您拥有的(非工作)类版本中的注释掉代码中添加您似乎一直在尝试使用的代码。但它有两个小问题。尽管如此,使用 new CustomPromise
的想法是正确的:
CustomPromise.resolve = value => new CustomPromise(fulfil => fulfil(value));
CustomPromise.reject = error => new CustomPromise((_, reject) => reject(error));
因此,如果您将其添加到
CustomPromise
函数定义下方,它将起作用。
其次,由于
catchers
应该有回调函数,所以你不应该将 value
推送给它,而是 failureCallback
:
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function CustomPromise(executor) {
var state=PENDING;
var value = null;
var handlers=[];
var catchers = [];
function resolve(result) {
if(state!==PENDING) return;
state=FULFILLED;
value = result;
handlers.forEach((h)=>h(value));
}
function reject(error) {
if(state!==PENDING)return;
state=REJECTED;
value=error;
catchers.forEach(c=>c(value));
}
this.then = function(successCallback) {
if(state === FULFILLED) {
successCallback(value);
}else {
handlers.push(successCallback);
}
return this;
}
this.catch = function(failureCallback) {
if(state===REJECTED){
failureCallback(value)
} else {
catchers.push(failureCallback); // Fix
}
}
executor(resolve,reject);
}
// Added:
CustomPromise.resolve = value => new CustomPromise(fulfil => fulfil(value));
CustomPromise.reject = error => new CustomPromise((_, reject) => reject(error));
// Demo
let p = CustomPromise.resolve(42);
let q = CustomPromise.reject("custom error");
p.then(value => console.log("p", value));
q.catch(error => console.log("q", error));
免责声明:此 Polyfill 不符合 Promises/A+ 规范,但它会符合
Promise
的 ECMAScript 规范。
它存在的一些问题:
then
回调。 then
回调永远不应同步执行,而应始终通过排队作业调用(即异步)。catch
方法错误地返回未定义。它应该返回一个承诺。then
方法错误地返回与调用它相同的承诺。它应该返回一个不同的承诺,该承诺将通过回调返回的值进行解析。then
方法忽略第二个参数。它应该采用第二个函数作为拒绝回调(如catch
)。有很多正确的实现可以找到。我发布了我自己的 Promises/A+ 兼容实现在此答案中。它没有
resolve
和 reject
静态方法,但它需要与上面给出的相同的附加代码。