异步操作Promise

promise

所谓Promise对象,简单说就是一个容器,里面包含着某个未来才会结束的事件的结果。语法上讲,Promise是一个对象,从它可以获取异步操作的消息。

Promise对象有以下特点:

  • 对象的状态不受外界影响。Promise对象代表一个异步操作,有三个状态:pending(进行中),fulfilled(已完成),rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种结果发生,状态就会凝固,不会再改变,会一直保持该结果,此时为resolved(已定型)。如果改变已经发生,你再对Promise对象添加回调函数,也会立即得到该结果。

  注意:无法取消Promise,一旦新建它就会立即执行,无法取消

基本用法:

promise对象只是一个构造函数,用来生成Promise实例。

 Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。

resolve函数的作用是:将Promise对象的状态从“未完成”变成“成功”,在异步操作成功时调用,并将异步操作的结果作为参数传递出去;

reject函数的作用是:将Promise对象的状态从“未变成”变成“失败”,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

  • Promise实例生成后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

 

 

第一个回调函数是Promise对象的状态变成resolved时调用,第二个回调函数时Promise对象的状态变成rejected时调用;这两个函数不一定都要提供。他们都接受Promise对象传出的值作为参数。

 

Promise新建后就会立即执行。看下例:

 

 

 首先输出的时Promise中的值,然后then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。

 

 

上面代码中,p1是一个 Promise,3 秒之后变为rejectedp2的状态在 1 秒之后改变,resolve方法返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1变为rejected,导致触发catch方法指定的回调函数。

 

注意,调用resolvereject并不会终结 Promise 的参数函数的执行。

调用resolve(××)以后,后边的代码操作还是会执行,并且会首先打印出来。因为立即resolved的Promise是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。

一般来说,调用resoleve或reject以后,Promise的使命就完成了,后继操作应该放在then方法里边,而不应该直接卸载resolve或reject的后边。所以最好在他们前边加上return 这样就不会有意外情况。

 

 

 

  •  Promise.prototype.then

 promise实例具有then方法,也就是说,then方法是定义在原型对象上的。

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

  • Promise.prototype.catch() 

 

 

 

 

 reject()方法的作用,等同于抛出错误。可以在catch捕获 或者then后的reject函数中。

如下例:

 

 

 打印值为:1。then后不定义函数则在catch捕获,打印为:error---1。

如果Promise状态已经变成resolved,再抛出错误是无效的,会被捕获,等于没有抛出。因为Promise的状态一旦改变(即出现日resolve或者reject),就永久保持该状态,不会再变。

 一般来说,不要在then()方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。因为catch可以捕获then方法执行中的错误,而不使用then()方法的第二个参数。

一般总是建议,Promise 对象后面要跟catch()方法,这样可以处理 Promise 内部发生的错误。catch()方法返回的还是一个 Promise 对象,因此后面还可以接着调用then()方法。如果没有报错就会跳过carry()方法,直接执行后边的then。

  • Promise.prototype.finally()

finally()方法用于指定不管 Promise 对象最后状态如何,执行完then或catch方法后都会执行finallly方法指定的回调函数。

finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果

  •  Promise.all

promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例。

  • Promise.resolve

Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))

 

上面代码的变量p就是一个 Promise 对象。

上面代码中,setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.resolve()在本轮“事件循环”结束时执行,console.log('one')则是立即执行,因此最先输出.

  • Promise.reject

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected

const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))

p.then(null, function (s) {
  console.log(s)
});
// 出错了


--------------------文章摘自ECMAScript6入门阮一峰

 

posted @ 2021-02-23 14:38  阿兰儿  阅读(424)  评论(0编辑  收藏  举报