Promise请求

  1. return new Promise({resolve,reject}=>{ //resolve指成功处理,reject指失败处理
  2. //do something
  3. if(){
  4. resolve();
  5. }else{
  6. reject();
  7. }
  8. }).then(()=>{
  9. //调用了resolve() 成功处理
  10. //do something
  11. }).catch(()=>{
  12. //失败处理 do something
  13. })

在上述代码中,Promise会传入两个参数-resolve和reject
具体的流程图如下显示


aysnc/await请求

aysnc/await请求和Promise请求有相同之处,也是用于处理异步、同步请求等,而且在aysnc/await请求中能结合Promise请求进行更加复杂的顺序逻辑处理。

相对于Promise来说,aysnc/await较为简洁

function text1() {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log('我是第一个执行的console');
                resolve(true);
            }, 1500)
        })
    }

    async function allTest() {
        await text1();
        console.log('我是第二个执行的方法')
    }

    window.onload = function () {
        allTest();
    }

由上诉的代码中可以看到,aysnc/await方法减少了.then的代码块,使代码更加的间接易懂,async方法内只有等待await方法执行完返回参数之后才会继续执行下面一个方法。


由Promise和aysnc/await衍生的异步顺序问题

在Promise和aysnc/await组成的逻辑处理中,总会遇到顺序处理问题,下面就讲一下其中的逻辑处理顺序。

具体可以参考github上的前端面试题 — 常见异步笔试题 https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7

首先要知道js的逻辑处理中存在同步和异步,一旦处理到异步的时候,js会将异步处理放到一个任务队列中,先处理执行栈的同步任务,执行完之后才会执行任务队列。
任务队列中又存在两种任务:

  • 宏任务(macrotask)
  • 微任务(microtask)

那么宏任务主要包括script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)。
微任务主要包括Promise.then、MutaionObserver、process.nextTick(Node.js 环境)

需要注意的是,await操作基本等同于Promise.then(),也是一个异步处理操作

由于微任务的处理速度会比宏任务更快,所以存在任务队列中的任务一般都是先执行微任务之后才会执行宏任务。

//请写出输出内容
async function async1() {
    console.log('async1 start');
    await async2();
    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();
      console.log('promise2');
}).then(function() {
    console.log('promise3');
});
console.log('script end');

参考上面的代码
首先执行的是console.log(‘script start’) => 然后遇到setTimeout,那么将里面这段处理放入宏任务中 => 然后执行async1()方法 => 执行console.log(‘async1 start’) => 遇到await处理async2() => 执行console.log(‘async2’) => await后面的console.log(‘async1 end’)放入微任务中 => aysnc1()执行完,进入Promise => 执行console.log(‘promise1’) => 执行resolve,进入then,将console.log(‘promise3’)放入微任务中 => 执行console.log(‘promise2’) => Promise结束,执行console.log(‘script end’) => 先顺序输出微任务队列 => console.log(‘async1 end’) => console.log(‘promise3’) => 再顺序输出宏任务 => console.log(‘setTimeout’)
所以一个整体的顺序如下:

/*
script start
async1 start
async2
promise1
promise2
script end
async1 end
promise3
setTimeout
*/

所以一个整体的任务队列如下图(promise2更改为promise3)
image.png