Promise最全解!

一. Promise特性类问题

1.说说你理解的Promise

(1)代理对象: Promise 对象是一个代理对象。Promise对象接受传入的 executor(执行器)作为入参,将异步任务的成功和失败分别绑定到对应的处理方法上去。
(2)Promise对象的两个特点:
**三个状态:**一个 Promise 实例有三种状态:
• pending 状态,表示进行中。这是 Promise 实例创建后的一个初始态;
• fulfilled 状态,表示异步任务成功完成。这是在执行器中调用 resolve 后,达成的状态;
• rejected 状态,表示操作失败、被拒绝。这是在执行器中调用 reject后,达成的状态;
状态切换机制: Promise实例的状态是可以改变的,但它只允许被改变一次。当我们的实例状态从 pending 切换为 rejected 后,就无法再扭转为 fulfilled,反之同理。当 Promise 的状态为fulfilled 时,会触发其对应的 then 方法入参里的 onfulfilled 函数;当 Promise 的状态为 rejected 时,会触发其对应的 catch 方法入参里的 onrejected 函数。

2. Promise的出现是为了解决什么问题

为了解决大量异步链式调用出现的回调地狱问题。

3. Promise 常见方法有哪些?各自是干嘛的?

1.then(): 分别指定resolved状态和rejected状态的回调函数
第一参数: 状态变为resolved时调用
第二参数: 状态变为rejected时调用(可选))

2.catch(): 指定发生错误时的回调函数

3.Promise.all(iterable) ,返回一个新的 promise 对象,该 promise 对象在 所有的 promise 对象都成功的时候才会触发成功, 一旦有任何一个 promise 对象失败则立即触发该 promise 对象的失败。该 promise 也会用子 promise 的成功返回值或失败详情作为参数调用 promise 绑定的相应处理函数,成功的返回值为所有的promise对象的成功返回值组成的数组。

Promise.all 里的任务列表是按照顺序一个一个发起的。
但是它们是异步的,互相之间并不阻塞,每个任务完成时机是不确定的,尽管如此,所有任务结束之后,它们的结果仍然是按顺序地映射到resultList里,这样就能和Promise.all里的任务列表一一对应起来。

var p1 = Promise.resolve('1号选手');
var p2 = '2号选手';
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "3号选手");
}); 
Promise.all([p1, p2, p3]).then(values => { 
  console.log(values); //  ["1号选手", "2号选手", "3号选手"]
});
  1. Promise.race(iterable),这个方法顾名思义,就是取出响应最快的那个请求。返回一个promise对象,该promise对象在任意一个子 promise 被成功或失败后,会立即被触发成功或者失败。该 promise 也会用子 promise 的成功返回值或失败详情作为参数调用 promise 绑定的相应处理函数
var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "1号选手"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 50, "2号选手"); 
});

// 这里因为 2 号选手返回得更早,所以返回值以 2号选手为准
Promise.race([p1, p2]).then(function(value) {
  console.log(value); //  "2号选手"
});

5.Promise.resolve(value):它返回一个 Promise 对象,传入的参数分为以下两种:
传入的是promise对象,返回的Promise对象的最终状态由传入的promise对象的状态决定
传入的是一个值,返回的 Promise 对象状态为 fulfilled,同时这里的 value 会作为 then 方法中指定的 onfulfilled 的入参。
传入的是Thenable对象(指具有then方法的对象),Promise.resolve方法会将这个对象转为Promise对象,然后立即执行thenable对象的then方法

6.Promise.reject(reason): 返回一个状态为失败的Promise对象,并将reason传递给对应的处理方法。

4.promise的缺点

  • 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
  • Promise对象提供统一的的接口,使得控制异步操作更加容易

5.Promise缺点:

  • 无法取消,一旦新建它就会立即执行,无法中途取消;
  • 如果不设置回调函数,Promise内部抛出的错误,不会反映到外部;
  • 当处于pending状态时,无法得知目前进展到哪一个阶段(刚开始还是即将完成)

二. 面试代码类问题

1.Promise 中的处理函数是异步任务,then 方法中传入的任务是一个异步任务。

const promise = new Promise((resolve, reject) => {
    console.log(1);
    resolve();
    console.log(2);
});

promise.then(() => {
    console.log(3);
});

console.log(4);
// 1 2 4 3

生成Promise实例后,先打印1,resolve() 这个调用,作用是将 Promise 的状态从 pending 置为 fulfilled,这个新状态会让 Promise 知道“我的 then 方法中那个任务可以执行了”——注意是”可以执行了“,而不是说”立刻就会执行“。毕竟作为一个异步任务,它的基本修养就是要等同步代码执行完之后再执行。所以说数字 3 的输出排在最后。

  1. Promise 对象的状态只能被改变一次
const promise = new Promise((resolve, reject) => {
  resolve('第 1 次 resolve')
  console.log('resolve后的普通逻辑')
  reject('error')
  resolve('第 2 次 resolve')
})
 
promise
.then((res) => {
  console.log('then: ', res)
})
.catch((err) => {
  console.log('catch: ', err)
})
// resolve后的普通逻辑
// then:  第 1 次 resolve

3.Promise 值穿透问题

Promise.resolve(1)
  .then(Promise.resolve(2))   // then方法不识别
  .then(3)    // then方法不识别
  .then()     // then方法不识别
  .then(console.log)   // then方法终于识别
  // 1

then参数期望是函数,onFulfilled(成功态的处理函数)和 onRejected(失败态的处理函数)。传入非函数则会发生值穿透。值传透可以理解为,当传入then的不是函数的时候,这个then是无效的。

  1. 一个promise指定多个成功/失败回调函数, 都会调用吗?
    答:当promise改变为对应状态时都会调用
let p = new Promise((resolve, reject) => {
    resolve('Promise状态会被标记为resolved')
   // reject('Promise状态会被标记为rejected')
   // throw new Error('Promise状态会被标记为rejected')
});
p.then(
    value => {
        console.log('value1', value) // value1 Promise状态会被标记为resolved
    },
    reason => {
        console.log('reason1', reason)
    }
).then(
    value => {
        console.log('value2', value)     // value2 undefined
    },
    reason => {
        console.log('reason2', reason)
    }
)

5.promise如何串连多个操作任务?
(1) promise的then()返回一个新的promise, 可以开成then()的链式调用
(2) 通过then的链式调用串连多个同步/异步任务

new Promise((resolve, reject) => {
    setTimeout(() => {
        console.log("执行任务1(异步)")
        resolve(1)
    }, 1000);
}).then(
    value => {
        console.log('任务1的结果: ', value)
        console.log('执行任务2(同步)')
        return 2
    }
).then(
    value => {
        console.log('任务2的结果:', value)

        return new Promise((resolve, reject) => {
            // 启动任务3(异步)
            setTimeout(() => {
                console.log('执行任务3(异步))')
                resolve(3)
            }, 1000);
        })
    }
).then(
    value => {
        console.log('任务3的结果: ', value)
    }
)


6.中断promise链
(1)当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
(2)办法: 在回调函数中返回一个pending状态的promise对象
return new Promise(()=>{}) // 返回一个pending的promise 中断promise链

三、Promise 底层原理考察

手写Promise

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值