Detailed explanation of the Promise topic. After reading it, you are the Promise King

Title: Detailed explanation of Promise
date: 2022-09-15 21:41:06
tags:

  • Promise
  • es6
    categories:
  • Js

Detailed explanation of Promise

The explanation will involve some knowledge points such as the event cycle. If this is weak, you can first learn about the event cycle

Question 1

There is no need to enlarge the move. Let's start with a simple one. This is a topic I read in the article collection before

console.log("start");
setTimeout(() => {
    console.log("children2")
    Promise.resolve().then(() => {
        console.log("children3")
    })
}, 0)

new Promise(function(resolve, reject) {
    console.log("children4")
    setTimeout(function() {
        console.log("children5")
        resolve("children6")
    }, 0)
}).then(res => {
    console.log("children7")
    setTimeout(() => {
        console.log(res)
    }, 0)
});

//--Results--
// start
// children4
// children2
// children3
// children5
// children7
// children6
  1. When encountering such promise questions, the first thing I think of is the requirements of the author. Promise type questions are all about execution results. You only need to analyze the code line by line
  2. First execute the synchronized code, such as console.log("start") in the first line, so the first output is start
  3. The next line is executed to setTimeout. You should know that setTimeout is synchronous, but the callback function in it is asynchronous and should be placed in the macro task queue. At this time, the macro task queue has a function waiting to be executed
  4. Then the new Promise(...) in the next line. Since the function passed in is executed immediately, the second output is children4
  5. The next line encounters setTimeout again and executes. The actual parameter callback function is an asynchronous task, which is placed in the macro task queue. At this time, there are two functions waiting to be executed in the macro task queue
  6. Many people will look at then. Because the instance object of the new Promise(...) is still pending at this time, the first callback in then is not executed, so then is not considered first
  7. After the synchronization task is executed, check whether there are any functions to be executed in the micro task queue. Go to macro task execution. The first, that is, the first setTimeout(...), so the third output children2
  8. The value returned by Promise.resolve() in the next line is the promise instance object in success status, and the function in. then(..) behind it is placed in the micro task queue for execution
  9. After the first macro task is executed, you need to go to the micro task queue to check whether there are tasks to be executed. That is, after each macro task is executed, you need to go to the micro task queue to check whether there are tasks. The macro task can be executed only after the micro task queue is cleared.
  10. At this time, there is a task in the micro task queue, so it is executed; The fourth output is children3. The micro task queue is empty, and the macro task queue is executed
  11. Then the fifth output children5 executes resolve(...), and the new Promise() of the outer layer changes its status to Success
  12. Because the state of the outer new Promise(..) instance object changes, the first successful function in. then can be executed, and the accepted value is the actual parameter passed in by resolve (..). Of course, the functions in. then should also be placed in the micro task queue.
  13. Execute the task in the micro task queue, output children7 in the sixth row, and put the function in setTimeout(..) in the next row in the macro task queue
  14. View the micro task queue, empty; To execute tasks in macro tasks. The seventh output is children6; The res value is the actual parameter passed in by resolve(...) above

The first question is just "appetizer". Of course, if you understand the first question thoroughly, then the following questions are all "drinking food". This kind of event cycle questions should be better understood by drawing pictures. There are two queues to fill in tasks, which seems to be a little more comprehensive

Question 2

    new Promise((resolve, reject) => {
        console.log("external promise");
        resolve();
    }).then(() => {
        console.log("External first then");
        return new Promise((resolve, reject) => {
            console.log("inside promise");
            resolve();
        }).then(() => {
                console.log("Internal first then");
            }).then(() => {
                console.log("Internal second then");
            });
    }).then(() => {//Note: The object returned here is the last one The object returned by then is in the status of 'pending' for the first time
        //Note: So the first time it will be cached here is not to join the queue
        console.log("External second then");
    });

// --Results--
// External promise
// External first then
// Internal promise
// Internal first then
// Internal second then
// External second then
  1. Execute the synchronization task in the new Promise(..) first, and output the external promise first
  2. When resolve() is encountered, it indicates that the promise instance is in a successful state. Put the first. then() behind it in the micro task queue. The second. then() is temporarily stored because the previous. then() is still in the executing state
  3. When executing the micro task queue, the second outputs the external first then, triggering the new Promise behind the return, so the third outputs the internal promise, goes to resolve(), the promise status changes, the following first. then() is placed in the micro task queue, and the second. then() is temporarily stored
  4. Execute the micro task queue. The fourth output is the first then. The function in then() returns a new Promise instance by default, so it is the second The function in then() is put into the micro task queue. The second then in the fifth output is executed, and a new Promise instance object is returned.
  5. At this time, the first. then() on the outermost layer has a new Promise to return, so the second. then() is put in the micro task queue.
  6. Execute the micro task queue, so the sixth output external second then

Question 3

    new Promise((resolve, reject) => {
            console.log("external promise");
            resolve();
        }).then(() => {
            console.log("External first then");
            new Promise((resolve, reject) => {
                    console.log("inside promise");
                    resolve();
                }).then(() => {
                    console.log("Internal first then");
                }).then(() => {
                    console.log("Internal second then");
                });
        }).then(() => { 
            console.log("External second then");
        });

// --Results--
// External promise
// External first then
// Internal promise
// Internal first then
// External second then
// Internal second then

This question is actually the revised version of the second question

  1. First, execute the synchronization task in the new Promise(). The first one outputs an external promise. When it encounters resolve(), the new promise becomes a success status. The next one, the first. then(), is placed in the micro task queue, and the second. then(), is temporarily stored.
  2. The second output of the micro task queue is the first external then, and the synchronization task in the new Promise() is executed. Therefore, the third output of the internal promise changes the resolve() state, and the next first. then() is placed in the micro task queue, and the next. then() is temporarily stored.
  3. At this time, the. then()return being executed is undefined, so the last. then() outside is placed in the micro task queue.
  4. Execute the first one in the micro task queue, so the fourth output is the first then, and the return one is also an undefined one, and the later. then() is also placed in the micro task queue
  5. Next, execute the task in the next micro task queue, that is, the function in the outermost. then(), and the fifth output is the external second then
  6. The last micro task is the second then in the sixth output of the innermost. then()

More questions

    async function async1() {
        console.log("async1 start")
        await async2();
        //await async2(), the code here is equivalent to new Promise (()=>{async2()})
        //Put all the code behind await in. then()
        console.log("async1 end")
    };

    async function async2() {
        console.log("async2")
    };

    console.log("script start");

    setTimeout(function() {
        console.log("setTimeout")
    }, 0);

    async1();

    new Promise(function(resolve) {
        console.log("promise1")
        resolve()
    }).then(function() {
        console.log("promise2")
    });

    console.log("script end");


    // script start
    // async1 start
    // async2
    // promise1
    // script end
    // async1 end
    // promise2
    // setTimeout
    console.log("start");
    setTimeout(() => {
        console.log("children2")
        Promise.resolve().then(() => {
            console.log("children3")
        })
    }, 0)

    new Promise(function(resolve, reject) {
        console.log("children4")
        setTimeout(function() {
            console.log("children5")
            resolve("children6")
        }, 0)
    }).then(res => {
        console.log("children7")
        setTimeout(() => {
            console.log(res)
        }, 0)
    });

    // start
    // children4
    // children2
    // children3
    // children5
    // children7
    // children6
    var p = new Promise(resolve => {
        console.log(4);
        resolve(5);
    }).then(resolve => {
        console.log(resolve);
    });

    function func1() {
        console.log(1);
    };

    function fun2() {
        setTimeout(() => {
            console.log(2);
        });
        func1();
        console.log(3);

        new Promise(resolve => {
            resolve();
        }).then(resolve => {
            console.log('new resolve');
        })

        p.then(resolve => {
            console.log(7);
        }).then(resolve => {
            console.log(6);
        });
    }
    fun2()

    // 4
    // 1
    // 3
    // 5
    // New resolution
    // 7
    // 6
    // 2
async function async1() {
        console.log('async1 start');
        const result = await async2();
        console.log(result);
        // The system will first execute the async2 function, then jump out of async1, and put the returned promise into the micro queue
        console.log('async1 end');
    }
    async function async2() {
        console.log('async');
        return "testAwait";
    }
    console.log('script start');
    setTimeout(function() {
        console.log('setTimeout');
    }, 0);
    async1();
    new Promise(function(resolve) {
        console.log('promise1');
        resolve();
    }).then(function() {
        console.log('promise2');
    });
    new Promise(function(resolve) {
        console.log('promise3');
        resolve();
    }).then(function() {
        console.log('promise4');
    });
    console.log('script end');

    // script start
    // async1 start
    // async
    // promise1
    // promise3
    // script end
    // testAwait
    // async1 end
    // promise2
    // promise4
    // setTimeout

Tags: Front-end Javascript ECMAScript

Posted by newbiehacker on Fri, 16 Sep 2022 02:40:13 +0930