-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
手写一个符合Promises/A+规范的promise #119
Labels
Comments
具体实现讲解可参考这里 const PENDING = "PENDING";
const RESOLVED = "RESOLVED";
const REJECTED = "REJECTED";
const resolvePromise = (promise2, x, resolve, reject) => {
console.log(promise2);
if (promise2 === x) {
// # 2.3.1 If promise and x refer to the same object, reject promise with a TypeError as the reason.
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
// 防止多次调用成功和失败
// # 2.3.3.3.3 If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.
let called;
try {
// 取x的then属性,如果是一个函数,认定其为promise
let then = x.then;
if (typeof then === "function") {
// # 2.3.3.3 If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise
then.call(
x,
(y) => {
// # 2.3.3.3.1 If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).
// 采用promise的成功结果将值向下传递
// 这里的y有可能还是一个promise,所以递归调用resolvePromise
if (called) {
return;
}
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
// # 2.3.3.3.2 If/when rejectPromise is called with a reason r, reject promise with r
// 采用失败结果向下传递
if (called) {
return;
}
called = true;
reject(r);
}
);
} else {
// 说明x是一个普通对象
resolve(x);
}
} catch (e) {
if (called) {
return;
}
called = true;
reject(e);
}
} else {
// x是一个普通值
// # 2.3.4 If x is not an object or function, fulfill promise with x
resolve(x);
}
};
class Promise {
constructor(executor) {
this.status = "PENDING"; // 默认pending状态
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.status === PENDING) {
this.value = value;
this.status = RESOLVED;
this.onResolvedCallbacks.forEach((fn) => fn());
}
};
let reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject); // 默认执行器会立即执行
} catch (error) {
reject(e);
}
}
then(onfulfilled, onrejected) {
// onfulfilled onrejected是可选参数
// # 2.2.1 Both onFulfilled and onRejected are optional arguments:
onfulfilled =
typeof onfulfilled === "function" ? onfulfilled : (data) => data;
onrejected =
typeof onrejected === "function"
? onrejected
: (err) => {
throw err;
};
let promise2 = new Promise((resolve, reject) => {
if (this.status === RESOLVED) {
setTimeout(() => {
try {
// # 2.2.2 If onFulfilled is a function:
// # 2.2.2.1 it must be called after promise is fulfilled, with promise’s value as its first argument.
let x = onfulfilled(this.value);
// x可能是普通值 也可能是promise
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
// # 2.2.3 If onRejected is a function,
// # 2.2.3.1 it must be called after promise is rejected, with promise’s reason as its first argument.
let x = onrejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onfulfilled(this.value);
// x可能是普通值 也可能是promise
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onrejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
}
// resolve方法
Promise.resolve = function (val) {
return new Promise((resolve, reject) => {
resolve(val);
});
};
// reject方法
Promise.reject = function (val) {
return new Promise((resolve, reject) => {
reject(val);
});
};
// race方法
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
};
// all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
No description provided.
The text was updated successfully, but these errors were encountered: