Write to meet the PromiseA+ specification source code (part 1)

The Promise object cannot be chain-called

const promise = new MyPromise((resolve, reject) => {
    resolve("hello");
});
promise.then().then().then().then(value => {
    return value;
}).then((value) => {
    console.log("fulfilled", value)
}, (reason) => {
    console.log("rejected", reason)
})
Copy the code

Problem analysis

  • PromiseA + Specification 2.2.7 then must return a promise [3.3]. The then method must return a Promise object after execution so that the chain call can be made.
  • The value x returned by the previous THEN function needs to be received, and the type of x needs to be judged and processed. The resolvePromise method is encapsulated for processing, and x is assumed to be ordinary value processing. This function will be described in detail below.
  • Value passing is required when the argument in then is null.

The solution

  • The then method needs to return a Promise object after execution.
  • OnFulFilled () = onFulFilled (); onFulFilled () = onFulFilled (); onFulFilled () = onFulFilled (); onFulFilled () = onFulFilled ();

Example 2:

then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value; onRejected = typeof onRejected === "function" ? onRejected : (reason) => { throw reason }; let promise2 = new MyPromise((resolve, reject) => { if (this.status === FULFILLED_STATUS) { try { let x = onFulfilled(this.value); resolve(x); } catch (e) { reject(e); }}... }); return promise2; }Copy the code

Continue to refine the above code

The problem background

  • When x returns as a promise, the promise needs to be processed further, encapsulating the resolvePromise methodCopy the code

Call way

const promise = new MyPromise((resolve, reject) => {
    resolve("hello");
});
promise.then(value => {
    return new MyPromise((resolve, reject) => {
        resolve(new MyPromise((resolve, reject) => {
            resolve(new MyPromise((resolve, reject) => {
                resolve('success');
            }))
        }))
    })
}).then((value) => {
    console.log("fulfilled", value)
}, (reason) => {
    console.log("rejected", reason)
})
Copy the code

Fulfillmypromise {status: “fulfilled”, value: MyPromise, reason: undefined, onFulfillCallbacks: fulfillmypromise {fulfillmypromise: fulfilled”, value: MyPromise, reason: undefined, onFulfillCallbacks: fulfillmypromise Array(0), onRejectCallbacks: Array(0)}, this should be fulfilled.

Example 3

Modify the then method and add resolvePromise method to handle the return value x.

Introduction to the resolvePromise method

The first step is to determine whether x is a Promise object. If so, get the return value from the promise. Otherwise, resolve. You need to determine if X and promise are equal, and if they are, you'll have circular references. Determine the Promise method, which is not null, is of type Object or function, and has a then method. Since there may be further nested promises, the resolvePromise needs to be called recursively.Copy the code

Circular reference invocation

const promise = new MyPromise((resolve, reject) => {
    resolve("hello");
});
const promise2 = promise.then(value => {
    return promise2;
});
promise2.then((value) => {
    console.log(value);
})
Copy the code

Optimized code

setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); }}, 0); function resolvePromise(promise, x, resolve, Reject) {if (promise === x) {// Avoid looping references return Reject (new TypeError('Chaining cycle detected for promise #< promise >'));  } let called; if (x ! == null && (["function", "object"]. Includes (typeof x)) {// Check whether x is a Promise. if (typeof then === "function") { then.call(x, y => { if (called) return; called = true; ResolvePromise (promise, y, resolve, reject); }, r => { if (called) return; called = true; reject(r); }) } else { resolve(x); } } catch (e) { if (called) return; called = true; reject(e); } } else { resolve(x); }}Copy the code