Post the topic first
Public number: hand touch hand front step
Promise.resolve().then(() = > {
console.log(0);
return Promise.resolve(4);
}).then((res) = > {
console.log(res)
})
Promise.resolve().then(() = > {
console.log(1);
}).then(() = > {
console.log(2);
}).then(() = > {
console.log(3);
}).then(() = > {
console.log(5);
}).then(() = >{
console.log(6);
})
Copy the code
After reading this question, what is your answer?
0 -> 2 -> 3 -> 4 -> 5 -> 6
So, did you do it right?
Is not like me entangled for wool 4 ran in the back of 3 😂
Here is my own understanding:
First of all, we know that microtasks are performed alternately
Here is an example:
So the first time I did it, the answer was: 0-> 1 -> 4 -> 2 -> 3 -> 5 -> 6
But the actual output of the fourth round missed twice, running behind the third
So if I change output 4, what does it say?
Amazing🤩, the result is 0->1->4->2->3->5->6
OK ~, with such doubts, I seem to understand a little, and went to look at the Promsie source code I learned before, and finally came to the following conclusions:
If the return value is a nested Promise object, the current THEN method must evaluate its final value and pass it back to the next THEN callback. Check if the value is a Promise object, so two more microtasks.)
Attached handwritten Promise source code:
const PENDING = 'pending'; / / wait for
const FULFILLED = 'fulfilled'; / / success
const REJECTED = 'rejected'; / / fail
class MyPromise {
constructor (executor) {
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e); }}/ / promsie state
status = PENDING;
// Value after success
value = undefined;
// Cause of failure
reason = undefined;
// Successful callback
successCallback = [];
// Failed callback
failCallback = [];
resolve = value= > {
// If the state is not waiting to prevent the program from executing down
if (this.status ! == PENDING)return;
// Change the status to success
this.status = FULFILLED;
// Save the value after success
this.value = value;
// Determine if the successful callback exists
// this.successCallback && this.successCallback(this.value);
while(this.successCallback.length) this.successCallback.shift()()
}
reject = reason= > {
// If the state is not waiting to prevent the program from executing down
if (this.status ! == PENDING)return;
// Change the status to failed
this.status = REJECTED;
// Cause of save failure
this.reason = reason;
// Determine if the failed callback exists
// this.failCallback && this.failCallback(this.reason);
while(this.failCallback.length) this.failCallback.shift()()
}
then (successCallback, failCallback) {
// Parameters are optional
successCallback = successCallback ? successCallback : value= > value;
// Parameters are optional
failCallback = failCallback ? failCallback: reason= > { throw reason };
let promsie2 = new MyPromise((resolve, reject) = > {
// Determine the status
if (this.status === FULFILLED) {
setTimeout(() = > {
try {
let x = successCallback(this.value);
// Determine whether x is a normal value or a promise object
// Call resolve directly if it is a normal value
// If it is a Promise object, look at the results returned by promsie
// Call resolve or reject based on the result returned by the Promise object
resolvePromise(promsie2, x, resolve, reject)
}catch(e) { reject(e); }},0)}else if (this.status === REJECTED) {
setTimeout(() = > {
try {
let x = failCallback(this.reason);
// Determine whether x is a normal value or a promise object
// Call resolve directly if it is a normal value
// If it is a Promise object, look at the results returned by promsie
// Call resolve or reject based on the result returned by the Promise object
resolvePromise(promsie2, x, resolve, reject)
}catch(e) { reject(e); }},0)}else {
/ / wait for
// Store the success and failure callbacks
this.successCallback.push(() = > {
setTimeout(() = > {
try {
let x = successCallback(this.value);
// Determine whether x is a normal value or a promise object
// Call resolve directly if it is a normal value
// If it is a Promise object, look at the results returned by promsie
// Call resolve or reject based on the result returned by the Promise object
resolvePromise(promsie2, x, resolve, reject)
}catch(e) { reject(e); }},0)});this.failCallback.push(() = > {
setTimeout(() = > {
try {
let x = failCallback(this.reason);
// Determine whether x is a normal value or a promise object
// Call resolve directly if it is a normal value
// If it is a Promise object, look at the results returned by promsie
// Call resolve or reject based on the result returned by the Promise object
resolvePromise(promsie2, x, resolve, reject)
}catch(e) { reject(e); }},0)}); }});return promsie2;
}
finally (callback) {
return this.then(value= > {
return MyPromise.resolve(callback()).then(() = > value);
}, reason= > {
return MyPromise.resolve(callback()).then(() = > { throw reason })
})
}
catch (failCallback) {
return this.then(undefined, failCallback)
}
static all (array) {
let result = [];
let index = 0;
return new MyPromise((resolve, reject) = > {
function addData (key, value) {
result[key] = value;
index++;
if(index === array.length) { resolve(result); }}for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
/ / promise object
current.then(value= > addData(i, value), reason= > reject(reason))
}else {
/ / common valuesaddData(i, array[i]); }}})}static resolve (value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve= >resolve(value)); }}function resolvePromise (promsie2, x, resolve, reject) {
if (promsie2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof MyPromise) {
/ / promise object
// x.then(value => resolve(value), reason => reject(reason));
x.then(resolve, reject);
} else {
/ / common valuesresolve(x); }}module.exports = MyPromie;
Copy the code
A Promsie interview question that Kept me up