es6中promise用法详解

1.含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

2.特点

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。

3.用法

ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。

const promiseA = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolvereject它们是两个函数,由 JavaScript 引擎提供,不用自己部署。调用promiseA函数时,必须执行resolve('成功参数')reject('失败参数')其中之一(可以不传参数)!否则就一直是pending状态。

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

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

 

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

promiseA.then(function(value) {
  // success
}, function(error) {
  // failure
});

then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数

 

const p1 = new Promise(function (resolve, reject) {
  // ...
});

const p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);
})

这里,p1的状态决定了p2的状态。如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行。

4. Promise.prototype.then() 

then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。

采用链式的then,可以指定一组按照次序调用的回调函数。执行顺序的规则是:

首先,同步的操作依次按照顺序执行,其次再是执行异步操作,且异步操作按照耗时多少的顺序输出结果。

    var p=new Promise(function (resolve,reject) {
        console.log('start')
		setTimeout(function (){
			console.log(111)
			resolve();
		}, 1000)	
	})
    
    p.then(v=>{
		console.log(222)
		setTimeout(function () {
			console.log(333)
		}, 3000)
	}).then(v=>{
		console.log(444)
	}).then(v=>{
		setTimeout(function () {
			console.log(555)
		}, 2000)
		console.log(666)
	})

结果为:立即输出 start,1秒后输出111,再立即依次输出222,444,666,再过2秒输出555,再过1秒输出333

再看一个复杂的例子:

    var p1=new Promise(function (resolve,reject) {
        console.log('start')
		setTimeout(function (){
			console.log("000")
			resolve();
		}, 1000)	
	})
	var p2=new Promise(function (resolve,reject) {
        console.log('start2')
		setTimeout(function (){
			console.log(111)
			resolve(p1);
		}, 1000)	
	})
    p2.then(v=>{
		console.log(222)
		setTimeout(function () {
			console.log(333)
		}, 4000)
	}).then(v=>{
		console.log(444)
	}).then(v=>{
		setTimeout(function () {
			console.log(555)
		}, 1000)
		console.log(666)
	})
    p1.then(v=>{
		console.log(777)
		setTimeout(function () {
			console.log(888)
		}, 3000)
	}).then(v=>{
		console.log(999)
	}).then(v=>{
		setTimeout(function () {
			console.log(101010)
		}, 2000)
		console.log(111111)
	})

p1和p2都会立即执行,promise内部同步操作优先于异步操作,先输出start和start2,然后p2以p1的结果作为参数,所以会等待p1执行完(resolve或reject),再立即执行,即先等一秒立即输出 000,此时p1为resolve,立即执行then的同步操作,输出 777 999 111111,等待完成p1执行结束,再立即执行p2的同步操作,输出 111 222 444 666,此时同步操作全部执行完毕。接着执行异步操作,四个异步操作按耗时计算,依次输出555,101010,888,333

5.Promise.prototype.catch()

Promise.prototype.catch方法是.then(null, rejection).then(undefined, rejection)的别名,用于指定发生错误时的回调函数。可以捕捉到promise内的错误和reject方法执行,以及它前面的then回调里面的错误。当promise内状态为reject时,它前面的then方法都不执行,直接执行catch方法,但是它之后的then方法不受影响秒回继续执行。

一般来说,不要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。

6.Promise.prototype.finally()

finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作,与then和catch同一级别的位置。该方法是 ES2018 引入标准的。

7.Promise.all()

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

const p = Promise.all([p1, p2, p3]);

p的状态由p1p2p3决定,分成两种情况。

(1)只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。

p.then([r1,r2,r3]=>{
    console.log(r1,r2,r3)
}).catch(err=>{
    console.log(err)
})

(2)只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

p.then(result=>{
    console.log(r1,r2,r3)
}).catch(err=>{
    console.log(err)
})

8.Promise.race()

Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。但是与all不同的是,只要p1p2p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

9.Promise.resolve()

Promise.resolve方法可以将现有对象转为 Promise 对象,然后就可以使用then回调的链式调用。

 

参考:http://es6.ruanyifeng.com/#docs/promise

 

 

 

 

 

 

 

你可能感兴趣的:(原生javascript)