ES6学习记录1--Promise

309 阅读3分钟

Promise对象

Promise对象有以下两个特点。

  1. 对象的状态不受外界影响。Promise对象代表一个异步操作。有三种状态,Pending(进行中)、fulfilled(已成功)和rejected(已失败)。
  2. 一旦状态改变,就不会再变

Promise也有一些缺点:

  1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
  2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。(所以在做网站错误监控的时候要做一个unhandledRejection的监听)
  3. 当处于pending状态时,无法得知目前进展到哪一个阶段。

基本用法

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

const Promise = new Promise((resolve, reject) => {
    if (/* 异步操作成功 */) {
        resolve(value);
	} else {
        reject(error);
    }
})

resolve函数的作用

reject函数的作用

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

promise.then(value => {
	// success
}, error => {
	// failure
});

其他的基础Promise知识不再记录了。

Promise.all()

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

// 参数可以不是数组,但是必须具有Iterator接口,且返回的每个成员都是Promise实例,
// 如果不是Promise实例,那么会调用下面讲到的Promise.resolve()方法,转为Promise实例
const p = Promise.all([p1,p2,p3]);

p的状态由p1、p2、p3决定,分2种情况:

  1. 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
  2. 只要p1、p2、p3之中有一个的状态变成rejected,p的状态就会变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
const promises = [2,3,4,5].map(item => {
	return getJSON('/post/' + item + '.json');
});
/**
* promises中的错误都由Promise.all()的catch捕捉,
* 如果promises中的Promise实例自己有catch的话就由自己的catch捕捉
*/ 
Promise.all(promises).then(posts => {
	// ...
}).catch(reason => {
	// ...
});

Promise.race()

Promise.race()方法同样将多个Promise实例,包装成一个Promise实例。

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

只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。

Promise.allSettled()

Promise.allSettled()方法是ES2020提出的,接收一组Promise实例作为参数,包装成一个新的Promise实例。

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

只有等到p1、p2、p3实例都返回结果,无论是fulfilled还是rejected,包装实例才会结束。

Promise.any()

Promise.any()目前是一个第三阶段的提案,接收一组Promise实例作为参数,包装成一个新的Promise实例。

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

只要p1、p2、p3有一个变成fulfilled,p的状态就变成fulfilled状态;只有所有的实例p1、p2、p3都变成rejected状态,p才会变成rejected状态。

Promise.resolve()

将现有对象转为Promise对象。

Promise.resolve方法的参数分成4种情况。

  1. 参数是一个Promise实例:将原封不动的返回这个Promise实例

  2. 参数是一个thenable对象

    // thenable对象指的是具有then方法的对象
    let thenable = {
    	then: function(resolve, reject) {
    		resolve(42);
    	}
    };
    

    Promise.resolve方法会将这个对象转为Promise对象,然后立即执行thenable对象的then方法。

  3. 参数不是具有then方法的对象,或根本不是对象:返回一个新的Promise对象,状态为resolved。

    const p = Promise.resolve('Hello');
    p.then(function(s){
    	console.log(s);
    });
    
  4. 不带有任何参数:直接返回一个resolved状态的Promise对象。

    const p = Promise.resolve();
    p.then(function() {
    	// ...
    })
    

Promise.reject()

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

Promise.reject()方法的参数,会原封不动的作为reject的理由,变成后续方法的参数,这与Promise.resolve方法不一致。

const thenable = {
  then(resolve, reject) {
    reject('出错了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable) // true
})

Promise.try()

如果你不知道或者不想区分某个函数是同步函数还是异步函数,例如下面代码中的database.users.get()方法,那么你就可以用Promise.try()来处理。这目前也只是一个提案。

Promise.try(() => database.users.get({id: userId}))
  .then(...)
  .catch(...)