由一道bilibili面试题看Promise异步执行机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由一道bilibili面试题看Promise异步执行机制相关的知识,希望对你有一定的参考价值。

参考技术A

求上面的输出顺序和输出值,为什么?

答案:

其中,关于时间差结果可能因为计算机性能造成的微小差异,可忽略不计

你答对了吗?下面我们由浅入深探索本题

首先,看一下 event loop 的基础必备内容

event loop 执行顺序:

微任务包括: MutationObserver 、 Promise.then()或catch() 、 Promise为基础开发的其它技术,比如fetch API 、 V8 的垃圾回收过程、 Node独有的process.nextTick 、 Object.observe (已废弃; Proxy 对象替代)

宏任务包括 : script 、 setTimeout 、 setInterval 、 setImmediate 、 I/O 、 UI rendering 、 postMessage 、 MessageChannel

注意: 下面的题目都是执行在浏览器环境下

遇到不好理解的,可结合 promise 源码 进行理解,就很简单了

解析:

解析:

解析:

解析:

解析:

解析:

解析:

解析:

现在看,本题就很简单了

解析:

promise知识点以及面试题

1.面试题

2.

目录
  • 常见 Promise 面试题
  • Promise 出现的原因
  • 什么是 Promise
  • Promsie 与事件循环
  • Promise 的升级
  • 结语     

    Promise 出现的原因

    在 Promise 出现以前,我们处理一个异步网络请求,大概是这样:

    
    // 请求 代表 一个异步网络调用。
    // 请求结果 代表网络请求的响应。
    请求1(function(请求结果1){
        处理请求结果1
    })
    复制代码

    看起来还不错。
    但是,需求变化了,我们需要根据第一个网络请求的结果,再去执行第二个网络请求,代码大概如下:

    请求1(function(请求结果1){
        请求2(function(请求结果2){
            处理请求结果2
        })
    })
    复制代码

    看起来也不复杂。
    但是。。需求是永无止境的,于是乎出现了如下的代码:

    请求1(function(请求结果1){
        请求2(function(请求结果2){
            请求3(function(请求结果3){
                请求4(function(请求结果4){
                    请求5(function(请求结果5){
                        请求6(function(请求结果3){
                            ...
                        })
                    })
                })
            })
        })
    })
    复制代码

    这回傻眼了。。。 臭名昭著的 回调地狱 现身了。

    更糟糕的是,我们基本上还要对每次请求的结果进行一些处理,代码会更加臃肿,在一个团队中,代码 review 以及后续的维护将会是一个很痛苦的过程。

    回调地狱带来的负面作用有以下几点:

    • 代码臃肿。
    • 可读性差。
    • 耦合度过高,可维护性差。
    • 代码复用性差。
    • 容易滋生 bug。
    • 只能在回调里处理异常。

    出现了问题,自然就会有人去想办法。这时,就有人思考了,能不能用一种更加友好的代码组织方式,解决异步嵌套的问题。

    let 请求结果1 = 请求1();
    let 请求结果2 = 请求2(请求结果1); 
    let 请求结果3 = 请求3(请求结果2); 
    let 请求结果4 = 请求2(请求结果3); 
    let 请求结果5 = 请求3(请求结果4); 
    复制代码

    类似上面这种同步的写法。 于是 Promise 规范诞生了,并且在业界有了很多实现来解决回调地狱的痛点。比如业界著名的 Qbluebirdbluebird 甚至号称运行最快的类库。


    Promise的使用总结。

    Promise 这么多概念,初学者很难一下子消化掉,那么我们可以采取强制记忆法,强迫自己去记住使用过程。

    • 首先初始化一个 Promise 对象,可以通过两种方式创建, 这两种方式都会返回一个 Promise 对象。

      • 1、new Promise(fn)
      • 2、Promise.resolve(fn)
    • 然后调用上一步返回的 promise 对象的 then 方法,注册回调函数。

      • then 中的回调函数可以有一个参数,也可以不带参数。如果 then 中的回调函数依赖上一步的返回结果,那么要带上参数。比如
          new Promise(fn)
          .then(fn1(value){
              //处理value
          })
      复制代码
    • 最后注册 catch 异常处理函数,处理前面回调中可能抛出的异常。

    通常按照这三个步骤,你就能够应对绝大部分的异步处理场景。用熟之后,再去研究 Promise 各个函数更深层次的原理以及使用方式即可。



                    

以上是关于由一道bilibili面试题看Promise异步执行机制的主要内容,如果未能解决你的问题,请参考以下文章

从一道算法面试题看我国信息科技的原创性不足:查找包含所有元素的最短子数组

promise执行顺序

JavaScript中的异步 macrotask 和 microtask

Promise 对象及相关面试题

[js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist

4--面试总结-promise