Promises/A+(primary)
-
Terminology
“promise” is an object or function with a then method whose behavior conforms to this specification.
“thenable” is an object or function that defines a then method.
“value” is any legal JavaScript value (including undefined, a thenable, or a promise).
“exception” is a value that is thrown using the throw statement.
“reason” is a value that indicates why a promise was rejected. -
Requirements
A promise must be in one of three states: pending, fulfilled, or rejected.
-
Promise States
- When pending, a promise:
may transition to either the fulfilled or rejected state. - When fulfilled, a promise:
must not transition to any other state.
must have a value, which must not change. - When rejected, a promise:
must not transition to any other state.
must have a reason, which must not change.
- When pending, a promise:
Here, “must not change” means immutable identity (i.e. ===), but does not imply deep immutability.
-
the then Method
A promise must provide a then method to access its current or eventual value or reason.A promise’s then method accepts two arguments:
promise.then(onFulfilled, onRejected)- Both onFulfilled and onRejected are optional arguments:
- If onFulfilled is not a function, it must be ignored.
- If onRejected is not a function, it must be ignored.
- If onFulfilled is a function:
- it must be called after promise is fulfilled, with promise’s value as its first argument.
- it must not be called before promise is fulfilled.
- it must not be called more than once.
- If onRejected is a function,
- it must be called after promise is rejected, with promise’s reason as its first argument.
- it must not be called before promise is rejected. * it must not be called more than once.
-
onFulfilled or onRejected must not be called until the execution context stack contains only platform code.
-
onFulfilled and onRejected must be called as functions (i.e. with no this value).
then may be called multiple times on the same promise.- If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.
- If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.
-
then must return a promise .
promise2 = promise1.then(onFulfilled, onRejected);- If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure
- If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.
- If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.
- If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.
- Both onFulfilled and onRejected are optional arguments:
// MyPromise.js
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
/**
* new MyPromise的时候executor(执行器函数)就要被执行,所以放在构造函数中
* executor()函数为外部传入的同步函数
* 起初status的状态为pending状态,value和reason为undefinded
* 执行executor函数时使用try...catch函数捕获错误
* 因为executor(resolve,rejected)函数接收两个形参,皆为回调函数
* 在构造函数中定义resolve(),rejected()函数
* 在resolve(),rejected()函数中改变status,value或reason的值
* then(onFulfilled,onRejected)函数接收两个形参,皆为回调函数
* 调用then()函数的时候判断status的状态,
* 如果为fulfilled则执行onFulfilled()回调函数;
* 如果为rejected则执行onRejected回调函数。
* 此处的onFulfiled()函数和onRejected()函数为用户传入。
* 此时同步一次调用promise已经成功
*/
class MyPromise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
// 发布
this.onFulfilledCallbacks.forEach((fn) => {
fn();
});
}
};
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.value = reason;
// 发布
this.onRejectedCallbacks.forEach((fn) => {
fn();
});
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.value);
}
if (this.status === REJECTED) {
onRejected(this.value);
}
// 订阅
/**
* 此处采用了发布者订阅模式,但是不是很懂,此处只阐述业务逻辑
*
* 在executor()函数中执行异步代码,不会改变status(pending)的状态
* 分别将onFulfilled()和onRejected()函数放到onFulfilledCallbacks[]
* 和onRejectedCallbacks[]中
* 然后在resolve()函数和reject()函数中全部执行
*
*
* 至此,在executor()函数中执行异步方法完美解决
*
*/
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
onFulfilled(this.value);
});
this.onRejectedCallbacks.push(() => {
onRejected(this.value);
});
}
}
}
module.exports = MyPromise;
// index.js
const MyPromise = require("./MyPromise.js");
let promise = new MyPromise((resolve, reject) => {
// resolve("success");
// reject("error");
// throw new Error("Exception:Error");
setTimeout(() => {
resolve("Success");
}, 2000);
});
promise.then(
(value) => {
console.log("FulFilled:", value);
},
(reason) => {
console.log("onReject:", reason);
}
);
2021-06-18 09:02:26 星期五
浙公网安备 33010602011771号