关于阅读 ES6- Promise 整理的问题

1、简述ES6中的Promise对象

答:① Promise是一个构造函数,可以通过 new 关键字进行创建实例
② Promise是异步编程的一种解决方案。
③ Promise就像一个容器,里面存在着未来才会结束的事情结果。

2、Promise的特点

答:① Promise对象的状态不受外界的干扰,只有异步操作的结果才能决定最终的状态
② Promise的状态一旦改变,就不会再进行变化。

3、Promise有哪些状态及状态流转

答:① 有3种状态,有2种状态流转
② 三种状态分别是,pending(进行中)状态、fulfilled(已成功)状态、rejected(已失败)状态
③ 两种状态流转分别是,pending 变为 fulfilled状态、pending 变为 rejected状态

4、Promise的缺点

答:① 一旦建立Promise实例就会立即执行,中途不能取消;
② 如果不设置回调函数(then方法绑定的函数),Promise内部抛出的错误是没办法抛到外部;
③ 当状态在pending时,没有办法得知状态是刚刚开始还是即将完成。

5、怎么使用Promise对象

答:① 使用new关键字创建Promise的实例
② Promise构造函数接受一个函数作为参数,该函数的两个参数是resolve 和reject
③ 参数resolve和reject是函数,由JS引擎提供不用自己去部署
④ resolve函数的作用是将状态从pending变为fulfilled
⑤ reject函数的作用是将状态从pending变为rejected
⑥ 异步操作的结果或者错误可以通过 resolve 和 reject函数传递出去
⑦ Promise实例一经创建便执行,Pomise实例的then中的回调函数要等脚本的所有同步操作执行完才执行
⑧ resolve和reject不会中止Promise里代码的执行
⑨ 建议resolve和reject函数后面的代码放入Promise的then回调函数中,代码更加清晰美观
⑩ Promise的then回调可以有多个,后一个回调的参数是前一个回调的结果

let p = new Promise((resolve, reject) => {
 console.log('Promise')
  let a = 1;
  if(a === 1){
     resolve('a等于1')
     console.log('resolve is over')
   }else{
     reject('a不等于1')
     console.log('reject is over')
   }
})

p.then(res => {
 console.log(res)
 return '第一个then回调的结果'
}).then(res => {
  console.log(res)
}).catch(err => {
    console.log(err)
})

console.log(2222)

/*结果依次输出:
 'Promise'
  resolve is over
  2222
 'a等于1'
 '第一个then回调的结果'
*/

6、简述Promise.prototype.then(resFun, errFun)方法

答:① Promise.prototype.then() 方法是 Promise 状态从 pending 变为 resolved 的回调;
② Promise可以有多个 then 回调,第一个 then 回调函数的参数,是 resolve 抛出来的,后面的then回调参数是前一个then回调函数return的结果。
③ 参数resFun是成功的回调函数,errFun是失败的回调(即catch方法),一般不建议catch方法用then的第二参数表示。

// bad 写法
promise.then(function(data) {
    // success
}, function(err) {
    // error
});

// good 写法
promise.then(function(data) { //cb
    // success
}).catch(function(err) {
    // error
});

7、简述 Promise.prototype.catch() 方法

答:① Promise.prototype.catch() 方法是 Promise 状态从 pending 变为 rejected 的回调,用来捕捉发生的错误。
② Promise.prototype.catch() 是Promise.prototype.then(null, rejection)的别名。
③ Promise可以有多个 catch 回调,第一个 catch 回调的参数,是前面代码运行时抛出的错误,后面的 catch 回调参数则是前一个catch方法抛出的错误。
④ Promise 的 catch 返回的还是一个 Promise 对象,所以后面可以继续接着调用 catch 或者 then 方法。
⑤ Promise 的 catch 执行完后,如果后面还有 catch 或者 then 方法,会继续进行代码的执行。
⑥ 如果代码没有出错误,那么会跳过catch 方法,继续向后执行代码。
⑦ 如果代码出了错误,但是没有 catch 方法,那么错误不会抛到外层去。
⑧ 如果代码出了错误,那么这个错误是有‘冒泡’的性质,一直会往后传递,知道被catch捕捉到为止。
⑨ 在浏览器中,Promise内部出了错误,不会影响到Promise的外部代码,浏览器会打印错误提示,代码依然继续执行。
⑩ 在Node.js中,Promise内部出了错误,会有一个unhandledRejection事件专门监听未捕捉的rejection错误,此时中止进程且进程的退出码不为0。
⑩ 如果 Promise 的状态已经变成 resolved,在用 throw 抛出错误是无效的。

let p = new Promise((resolve, reject) => {
  let a = 1
  if(a > 1){
    resolve()
   }else{
    reject('error')
    throw new Error('error')  // 无效,因为Promise的状态已经变成resolved了
  }
})

p.then(res1 => { // res1是Promise的resolve抛出来的结果
   return 'res1的结果'
}).then(res2 => { // res2是上一个then方法return的结果
   a = y
   return 'res2的结果'
}).catch(err1 => { // 如果前面代码发生错误就会被捕捉到,没有就会跳过这个catch,继续往后执行其他代码
   console.log(111) 
   console.log(err1)   
   console.log(11111111111)
   return 'err1'
}).then(res3 => { // res3是上一个then方法return的结果
   a = dd
   console.log(222)
   console.log(res3) 
   console.log(221)
   return 'res3'
}).catch(err2 => { // 如果前面代码发生错误就会被捕捉到,没有就会跳过这个catch,继续往后执行其他代码
   console.log(3333)
   console.log(err2)
   console.log(331)
   y= www
   return 'err2'
}).catch(err3 => { // err3是前一个catch方法抛出的错误
  console.log(444)
  console.log(err3)  
  console.log(441)
  return 'err3'
})
/*输出结果为:
111
'error'
11111111111
3333
ReferenceError: dd is not defined at <anonymous>:22:5
331
444
ReferenceError: www is not defined at <anonymous>:31:5
441
*/

8、简述Promise.prototype.finally()方法

答:① 这个方法不管在Promise的fulfilled状态还是rejected状态,最后都会进行执行调用。
② 这个回调函数不接受任何的参数,不依赖于Promise的执行结果。本质上是then方法的特例。
③ finally方法总是会返回原来的值。

Promise.prototype.finally = function(callback){  // finally的具体实现
  let p = this.constructor;
  return this.then(
    res = > p.resolve(callback()).then(() => res),
    err =>  p.resolve(callback()).then(() => {throw err})
  )
}

promise.then((res) => {}).catch((err) => {}).finally(() => {}) // 一般写法

promise.then(
  res => {  return res;},
  error => {   throw error;  }
); // 等同于 promise.finally(() => {});

//  finally方法总是会返回原来的值
Promise.resolve(2).then(() => {}, () => {}) // resolve 的值是 undefined
Promise.resolve(2).finally(() => {}) // resolve 的值是 2
Promise.reject(3).then(() => {}, () => {}) // reject 的值是 undefined
Promise.reject(3).finally(() => {}) // reject 的值是 3

9、简述Promise.all()方法

答:① 该方法时将多个Promise实例,包装成一个新的Promise实例。
② 该方法的参数可以是数组,也可以是具有Iterator接口的对象。
③ Promise.all()方法中参数中的成员需要是Promise实例,如果不是,会自动使用Promise.resolve方法转换。

let p1 = new Promise(),   p2 = new Promise,   p3 = new Promise()
p1.then((res) => {});
p2.then((res) => {});
p3.then((res) => {});
// p1 p2 p3需是Promise的实例,如果不是则会自动使用Promise.resolve转换
let pAll = Promise.all([p1, p2, p3])

10、Promise.all()方法的状态是什么呢?

答:① 它的状态由传入参数成员的状态来决定。
② 如果成员的状态都是 fulfilled,那么 Promise.all()的状态就会变成 fulfilled。
③ 如果成员的状态有一个是rejected,Promise.all()的状态就是rejected,

let p1 = new Promise(),   p2 = new Promise,  p3 = new Promise()
p1.then((res) => {});
p2.then((res) => {}); 
p3.then((res) => {});

// 如果p1 p2 p3状态都是resolved,pAll状态是 fulfilled,否则是 rejected
let pAll = Promise.all([p1, p2, p3])

11、Promise.all()方法的回调函数的参数是什么呢?

答:① 如果Promise.all方法的参数成员状态都是resolved,此时Promise.all 的返回值就是所有成员返回值组成的数组,并传给Promise.all的回调函数。
② 如果Promise.all方法的参数成员状态有一个是rejected,那么第一个rejected的成员的返回值就是Promise.all回调函数的参数。

let p1 = new Promise(),   p2 = new Promise,   p3 = new Promise()
p1.then((res) => {});
p2.then((res) => {});
p3.then((res) => {});
let pAll = Promise.all([p1, p2, p3])

pAll.then(res => {
   // 如果p1 p2 p3状态都是resolved,那么res是它们返回值组成的数组
   // 如果p1 p2 p3状态有一个是rejected,那么res是第一个rejected的返回值
})

12、Promise.all()方法中参数成员本身rejected对Promise.all()方法catch的影响是什么?

答:① 如果参数成员本身定义了catch方法,那么被rejected时并不会触发Promise.all()的catch方法
② 如果参数成员本身没有定义catch方法,那么被rejected时会触发Promise.all()的catch()方法

const p1 = new Promise((resolve, reject) => {
  resolve('hello');
}).then(result => result).catch(e => e); // 状态会变成 resolved

const p2 = new Promise((resolve, reject) => {
  throw new Error('报错了');
}).then(result => result).catch(e => e); // 执行完catch方法后,p2的状态会变成 resolved

const p3 = new Promise((resolve, reject) => {
  resolve('hello');
}).then(result => result); // 状态会变成 resolved

const p4 = new Promise((resolve, reject) => {
  throw new Error('报错了');
}).then(result => result); // 没有catch方法,会调用 Promise.all中的catch方法来捕捉错误

Promise.all([p1, p2]).then(
   result => console.log(result)
).catch(
   e => console.log(e)
); // ["hello", Error: 报错了]

Promise.all([p3, p4]).then(
   result => console.log(result)
).catch(
   e => console.log(e)
); // Error: 报错了

13、简述Promise.race([成员1, 成员2…])方法

答:① 和Promise.all()方法的功能相同,都是将多个Promise实例包装成一个新的Promise实例
② 如果传入的参数成员不是Promise实例,那么会使用Promise.resolve转换一下。
③ 只要参数成员中有一个成员的状态率先发生了改变,那么Promise.race()的状态就跟着改变,
④ Promise.race()的返回值是第一个状态发生改变的参数成员的返回值。
const p = Promise.race([p1, p2, p3]) // 只要三个成员中有一个率先改变状态,p的状态就跟着改变

14、简述 Promise.allSettled()方法

答:① Promise.all()方法需要成员的状态都是resolved,只要有一个成员失败了,Promise.all()就会失败,无法进行下一步操作。
② Promise.allSettled()方法就是为了解决这个问题,也是接受一个由Promise实例组成的数组,只要参数数组成员的操作都结束(不管成功还是失败),Promise.allSettled()状态都是fulfilled,会进行下一步操作。
③ Promise.allSellted()方法的回调函数(then)的结果是一个数组对象,数组对象的格式固定,只有两种格式。

const resolved = Promise.resolve(42)
const rejected = Promise.reject(-1)
const allSettled = Promise.allSettled(resolved, rejected)

allSettled.then((res) => {
 console.log(res)
})

/*回调函数结果输出每个成员的操作结果:
 [
    { status: 'fulfilled', value: 42 }, // 成员操作成功时的格式
    { status: 'rejected', reason: -1 } // 成员操作失败时格式
 ]
*/

// 过滤出成功的请求
const suc = allSettled.filter(p => p.status === 'fulfilled');

// 过滤出失败的请求,并输出原因
const err = allSettled.filter(p => p.status === 'rejected').map(p => p.reason);

15、简述Promise.any()方法

答:① 该方法参数是一个数组,数组里面的成员是Promise实例。
② 当数组成员的所有成员的状态有一个是fulfilled,Promise.any()方法状态就是fulfilled状态
③ 当数组成员的所欲成员状态都是rejected,Promise.any()方法状态就是rejected状态

Promise.any([
  fetch('https://v8.dev/').then(() => 'home'),
  fetch('https://v8.dev/blog').then(() => 'blog'),
  fetch('https://v8.dev/docs').then(() => 'docs')
]).then((first) => {  // 只要有一个 fetch() 请求成功,就执行then回调
  console.log(first);
}).catch((error) => { // 所有三个 fetch() 全部请求失败,就执行catch回调
  console.log(error);
});

16、Promise.race()、Promise.any()、Promise.all()和Promise.allSettled()方法的区别

答:① 它们的参数都是数组,数组的成员都是Promise实例,如果不是,会自动使用Promise.resolve进行转换
② 它们最后的返回值都是一个新的Promise实例
③ Promise.race()的状态由第一个率先改变状态的数组成员决定,如果这个成员状态是rejected那么最后状态就是rejected,反之为fulfilled状态。
④ Promise.race()回调函数的入参是第一率先改变状态的成员返回值。
⑤ Promise.any()的状态由数组成员状态决定,全部成员状态为rejected,最后结果状态是rejected,有一个成员状态是fulfilled,最后结果是fulfilled
⑥ Promise.any()中,如果有一个成员状态是rejected,那么Promise.all()的回调函数的入参是被reject的返回值组成的数组,如果成员状态有一个是fulfilled,那么入参是参数成员返回值
⑦ Promise.all()方法中,如果参数成员有一个成员状态变为rejected,那么最后状态就会变成rejected,只有全部成员状态是fulfilled,最后状态才是fulfilled。
⑧ Promise.all()方法中,如果有一个成员状态是rejected,那么Promise.all()的回调函数catch的入参是第一个被reject的返回值,如果成员状态都是fulfilled,那么入参是参数成员返回值组成的数组。
⑨ Promise.allSettled()方法中,最后状态都是fulfilled
⑩ Promise.allSetteld()方法,回调函数接受一个数组对象作为入参,每个对象是对应成员的返回值,只有两种格式,格式如下:
{status: ‘fulfilled’, value: value} // 异步操作成功时
{status: ‘rejected’, reason: reason} // 异步操作失败时

17、简述Promise.resolve()方法

答:① 这个方法用于将一个对象转换成Promise对象
② Promise.resolve(xxx)等价于 new Promise(resolve => resolve(xxx))
③ Promise.resolve是在本轮事件循环结束时执行

setTimeout(function(){ 
  console.log('111')
}, 0) // 这行代码 会在下一轮的事件循环开始时执行

Promise.resolve().then(() => { 
  console.log(222)
}) // resolve会在本轮事件循环结束时执行

console.log(333) // 这行代码在本轮事件循环,立即执行

/*上面的执行输出依次是:
333
222
111
*/

18、简述Promise.resolve(x)方法的对不同参数类型的处理

答:① 当参数 x 为 Promise 实例,那么不对其做任何处理,直接返回
② 当参数 x 是一个 thenable 对象(具有then方法的对象),会将其先转为 Promise 对象,然后立即执行 thenable里面的then方法。
③ 当参数 x 是一个普通对象或者原始值,会返回一个新的 Promise 对象
④ 当没有参数的时候,会直接返回一个 resolved 状态的 Promise 对象

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);

p1.then(function (value) {
  console.log(value);  // 42
});

19、简述Promise.reject()方法

答:① 该方法也会返回一个Promise实例,状态为rejected。
② 该方法会将入参作为回调函数catch的参数
③ 该方法等同于 new Promise((resolve, reject) => reject())

var p = Promise.reject(111)
p.catch(err => {
 console.log(err)
}) // 111

20、Promise对象的应用有哪些

答:① 图片的加载
② 与Generator函数的结合

21、Promise.try()方法

答:该方法模拟try代码块,用来捕获所有的同步和异步错误。

Promise.try(() => {
  // 代码
}).then(...).catch(...);

22、让同步函数同步执行,异步函数异步执行,并让它们具有统一API的办法有哪些

答:① 匿名函数立即执行+async方法, (async () => fun())().then(…).catch(…)
② 匿名函数立即执行 + new Promise方法, (() => new Promise(resolve => resolve(fun())))()
③ 通过Promise.try方法,Promise.try(() => fun()).then(…).catch(…)

23、Promise的finally回调

答:这个回调是不管Promise在哪种状态(fulfilled还是rejected)都会执行的回调,
它的入参是一个函数,不管怎么样,这个函数都会执行。

let p = new Promise((resolve, reject) => {resolve(111)})

p.then( 
    res => console.log(res)
).catch(
    err => console.log(err)
).finally(
    () => console.log(2222)
)
/*输出结果:
111
2222
*/

24、Promise的done回调

答:这个方法总是处于回调链的尾端,可以捕捉到抛出的任何错误。


new Promise().then().then().catch().then().catch().then().done()

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值