美文网首页
Promise 精选部分面试题初探

Promise 精选部分面试题初探

作者: 酷酷的凯先生 | 来源:发表于2020-10-30 14:22 被阅读0次

# 前言

Promise : 英文意思是 承诺、许诺。
即先承诺后兑现,先发送请求,过段时间在给你数据,而这个时间可长可短。

综上所述:Promise 是一个异步编程的一种 解决方案,比传统的异步解决方案【回调函数】和【事件】更合理、更强大。现已被 ES6 纳入进规范中。

# Priomise 的由来

在 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 以及后续的维护将会是一个很痛苦的过程。

回调地狱的特点大概有以下几个:

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

能不能用一种更加友好的代码组织方式,解决异步嵌套的问题 ?
答案是肯定的,如下是最初提出的设想:

let 请求结果1 = 请求1();
let 请求结果2 = 请求2(请求结果1); 
let 请求结果3 = 请求3(请求结果2); 
let 请求结果4 = 请求2(请求结果3); 
let 请求结果5 = 请求3(请求结果4); 

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

Promise 规范诞生后最初的设想得以实现,如下代码所示:

new Promise(请求1)
    .then(请求2(请求结果1))
    .then(请求3(请求结果2))
    .then(请求4(请求结果3))
    .then(请求5(请求结果4))
    .catch(处理异常(异常信息))

# Promise 常用的API

一个 Promise 对象有三个状态:

  • pending,异步任务正在进行。
  • resolved, 异步任务执行成功。
  • rejected,异步任务执行失败。

并且状态一旦改变,便不能再被更改为其他状态,有且只有两种情况,如下:

  1. pending ==> resolved
  2. pending ==> rejected

1. Promise.resolve(value)

类方法,该方法返回一个以 value 值解析后的 Promise 对象
(1)、如果这个值是个 thenable(即带有 then 方法),返回的 Promise 对象会“跟随”这个 thenable 的对象,采用它的最终状态(指 resolved/rejected/pending/settled)
(2)、如果传入的 value 本身就是 Promise 对象,则该对象作为 Promise.resolve 方法的返回值返回。
(3)、其他情况以该值为成功状态返回一个 Promise 对象。

举个简单的小栗子:

// 如果传入的 value 本身就是 Promise 对象,
// 则该对象作为 Promise.resolve 方法的返回值返回
function fn(resolve){
    setTimeout(function(){
        resolve(1);
    },1000);
}

let p0 = new Promise(fn);
let p1 = Promise.resolve(p0);

console.log(p0 === p1); // true  返回的 Promise 即是 入参的 Promise 对象。

传入 thenable 对象,返回 Promise 对象跟随 thenable 对象的最终状态。

ES6 Promises 里提到了 Thenable 这个概念,简单来说它就是一个非常类似 Promise 的东西。最简单的例子就是 jQuery.ajax,它的返回值就是 thenable 对象。但是要谨记,并不是只要实现了 then 方法就一定能作为 Promise 对象来使用。

// 如果传入的 value 本身就是 thenable 对象,
// 返回的 promise 对象会跟随 thenable 对象的状态。
let p = Promise.resolve($.ajax('/test/test.json')); // => promise对象
p.then(function(value){
  console.log(value);
});

返回一个状态已变成 resolved 的 Promise 对象。

let p = Promise.resolve(1); 
console.log(p);  // 是一个状态置为resolved的Promise对象

2. Promise.reject(value)

类方法,且与 resolve 唯一的不同是,返回的 promise 对象的状态为 rejected

3. Promise.all( [ 多个 promise 组成的数组 ] )

类方法,多个 Promise 任务同时执行。
如果全部成功执行,则以数组的方式返回所有 Promise 任务的执行结果。
如果有一个 Promise 任务 rejected,则只返回 rejected 任务的结果。

4. Promise.race( [ 多个 promise 组成的数组 ] )

类方法,多个 Promise 任务同时执行,
返回最先执行结束的 Promise 任务的结果,不管这个结果是成功还是失败。

5. Promise.prototype.then

实例方法,为 Promise 注册回调函数,函数形式:fn(vlaue){},value 是上一个任务的返回结果

then 中的函数一定要 return 一个结果或者一个新的 Promise 对象,才可以让之后的then 回调接收。

# Promise 一般使用过程

  1. 首先初始化一个 Promise 对象,可以通过两种方式创建, 这两种方式都会返回一个 Promise 对象。
    (1)、new Promise(fn)
    (2)、Promise.resolve(fn)

  2. 然后调用上一步返回的 promise 对象的 then 方法,注册回调函数。

  3. then 中的回调函数可以有一个参数,也可以不带参数。如果 then 中的回调函数依赖上一步的返回结果,那么要带上参数。比如:

new Promise(fn).then(fn1(value){
  //处理value
})
  1. 最后注册 catch 异常处理函数,处理前面回调中可能抛出的异常。

总结:Promise 在初始化时,传入的函数是同步执行的,然后注册 then 回调。注册完之后,继续往下执行同步代码,在这之前,then 中回调不会执行。同步代码块执行完毕后,才会在事件循环中检测是否有可用的 promise 回调,如果有,那么执行,如果没有,继续下一个事件循环。

# 小试牛刀

读到这里,看下面记到面试题你能回答出来几道?

1、了解 Promise 吗?
2、Promise 解决的痛点是什么?
3、Promise 解决的痛点还有其他方法可以解决吗?如果有,请列举。
4、Promise 如何使用?
5、Promise 常用的方法有哪些?它们的作用是什么?
6、Promise 在事件循环中的执行过程是怎样的?
7、Promise 的业界实现都有哪些?

相关文章

  • Promise 精选部分面试题初探

    # 前言 Promise : 英文意思是 承诺、许诺。即先承诺后兑现,先发送请求,过段时间在给你数据,而这个时间可...

  • Promise async/await

    Promise async/await 参考初探promise promise 理解 JavaScript ...

  • Promise精选面试题

    一、前言 前端面试过程中,基本都会问到 Promise,如果你足够幸运,面试官问的比较浅,仅仅问 Promise ...

  • 初探Promise

    摘自:阮一峰 http://es6.ruanyifeng.com/#docs/promise 一、首先,我们要弄明...

  • Promise初探

    遭遇“恶魔金字塔” 项目需要,封装了一个省市区的地址选择器组件。 可以根据省份id、城市id和区id对组件设置默认...

  • Promise初探

    1. promise有什么用 promise提供了对js异步编程的新的解决方案。 他改变了传统回调的位置,不用去思...

  • promise使用初探

    title: promise使用初探date: 2018-12-29 16:10:48categories: 小游...

  • Promise面试题

    Promise面试题 题目一 解析首先Promise新建后立即执行,所以会先输出1,2,而Promise.then...

  • 2020年,精选大厂的iOS面试题总结(一)

    iOS面试题目录(一) 精选大厂的iOS面试题总结(一)精选大厂的iOS面试题总结(二) 1. iOS内存管理机制...

  • js.Promise 解决地狱回调

    之前见过的一道Promise面试题的答案

网友评论

      本文标题:Promise 精选部分面试题初探

      本文链接:https://www.haomeiwen.com/subject/ouzrvktx.html