摘要:promise,ES6新增特性,是javascript实现异步的方法之一,在这里对promise的基础知识做介绍。
promise
作用:异步编程的一种解决方案
三种状态:
- pending(进行中)
- fulfilled(已完成,又称resolved)
- rjected(已失败)
状态只有两种变化,状态只能从pending变化为fulfilled或者rjected,只有异步操作的结果可以决定当前是哪一种状态,并且状态一旦改变,就不会再发生变化。
- pending->fulfilled
- pending->rjected
使用例子
promise是一个构造函数,需要用new来生成promise的实例,在promise实例中执行的代码是同步执行的,即new之后代码是立即执行的,Promise实例化的时候传入的是一个函数,函数可接受两个参数,分别是resolve和reject,这两个参数其实是两个函数,当异步操作结束的时候进行调用。
- resolve:将实例的状态从Pending->fulfilled,并且将异步操作成功的结果作为参数传递出去
- reject:将实例的状态从Pending->rjected,并且将异步操作报出的错误作为参数传递出去
- promise.then:该方法接受两个回调函数作为参数,分别为onFulfilled和onRejected,即状态变为fulfilled和状态变为rejected的时候调用的函数
- promise.catch:该方法接受一个回调函数作为参数,其实就是捕获错误的函数
1 | var promise = new Promise(function(resolve, reject){ |
promise方法
prmoise提供的方法有一下6个,下面对这几个方法进行介绍
- Promise.prototype.then(onFulfilled, onRejected)
- Promise.prototype.catch(onRejected)
- Promise.all(iterable)
- Promise.race(iterable)
- Promise.resolve(iterable)
- Promise.reject(reason)
Promise.prototype.then(onFulfilled, onRejected)
Promise的实例具有then方法,调用之后会返回一个新的promise实例,如果then中有onRejected函数并且promise有reject错误,执行完then方法之后,返回的新promise实例的状态就会变为fulfilled。
then是Promise实例的回调函数,即当Promise实例的状态发生改变时调用的函数,它接受两个参数,第一个参数onFulfilled是当状态变为fulfilled的回调函数(执行resolve()函数),第二个参数是当状态变为rejected的回调函数(执行reject()函数)。
Promise实例的方法是可以链式调用的,看到下面的例子,第一个回调函数的返回值会传到下一个回调函数的参数中,如果第一个函数没有返回值,则第二个回调函数的参数则为undefined。(这里的第一行代码是直接调用Promise.resolve(),这其实是快速获取状态为resolved的promise实例)。1
2
3
4
5
6
7var promise = Promise.resolve();
promise.then(function(res){
console.log(res); // undefined
return 'next res';
}).then(function(res){
console.log(res); // 'next res'
});
Promise.prototype.catch(onRejected)
promise的实例也具有catch方法,用于捕获代码中抛出的异常(也包括reject抛出的异常),调用之后会返回一个新的promise实例,一旦错误被捕获,新promise实例的状态就是fulfilled。
异常也可以在then中被捕获,被then捕获的异常就不会被catch捕获了。示例一中promise抛出的错误被then的onRejected捕获了,onRejected中又抛出了错误,这里的错误就被catch捕获了。
Promise对象的错误是可以冒泡的,如果错误没有被捕获,就会一直像后传递直到被捕获为止。示例二中promise抛出的错误在then中没有被捕获,所以就会冒泡到catch中被捕获。
如果Promise对象已经执行了resolve()函数,在之后再抛出的错误就不会被捕获了,在示例三中Promise对象已经执行了resolve(),所以之后抛出的错误也不会被捕获,因为状态一旦改变,就不会再变了,所以后续的错误也不会被捕获。这里Promise对象抛出的错误不会传递到外层代码,所以也不会看到有报错。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 示例一:then中捕获promise中reject抛出的异常,catch中捕获onRejected抛出的异常
var promise = Promise.reject('err');
promise.then(null, function(err){
console.log(err); // 'err'
throw 'next err';
}).catch(function(err){
console.log(err); // 'next err'
});
// 示例二:error没有被then捕获,则会冒泡到catch中被捕获
promise.then().catch(function(err){
console.log(err); // 'err'
});
// 示例三:当promise的resolve之后,再之后抛出的错误就不会被捕获了
var promise = new Promise(function(resolve,reject){
resolve('123');
throw '456';
});
promise.then().catch(function(err){
console.log(err);
});
Promise.all(iterable)
Promise.all方法是将多个promise实例,包装成一个新的promise实例。
promise的状态由all中所有的promise的状态决定:
- fulfilled:当all中所有promise的状态都为fulfilled时promise的状态为fulfilled
- rejected:当all中其中一个promise的状态为rejected时promise的状态为rejected
promise的返回值为all中所有的返回值组成的数组。
如果promise参数数组中的对象不是promise对象,则会先调用Promise.resolve对象将其转化为promise对象。
iterable参数可以不是数组,但是必须含有Iterator接口。
示例中,promise2状态率先变为fulfilled,但是promise1的状态还是pending,所以promise的状态还是pending,过了5s之后,promise1的状态变为fulfilled,即all中所有的promise对象的状态都变为fulfilled,所以promise的状态就变为了fulfilled,返回值则为all中所有的返回值组成的数组。1
2
3
4
5
6
7
8
9
10
11
12
13var promise1 = new Promise(function(resolve){
setTimeout(function(){
resolve('123');
},5000);
});
promise1.then(function(res){
console.log(res);
});
var promise2 = Promise.resolve('456');
var promise = Promise.all([promise1,promise2]);
promise.then(function(res){
console.log(res); // ['123','456']
});
Promise.race(iterable)
Promise.race(iterable)方法是将多个promise实例包装成一个promise实例。promise的状态由race中promise的状态决定,率先改变状态的promise会把状态和返回值传递给promise。
示例中,promise是由promise1和promise2包装成的,promise2的状态率先转变为fulfilled,所以promise的状态就采用了promise2的状态和返回值。1
2
3
4
5
6
7
8
9
10
11
12
13var promise1 = new Promise(function(resolve){
setTimeout(function(){
resolve('123');
},5000);
});
promise1.then(function(res){
console.log(res);
});
var promise2 = Promise.resolve('456');
var promise = Promise.race([promise1,promise2]);
promise.then(function(res){
console.log(res); // '456'
});
Promise.resolve(iterable)
Promise.resolve(iterable)方法返回一个新的promise实例,实例的状态为fulfilled。
这里可以分三种情况:
- 参数为promise实例:
此时返回的是传入的promise实例,看到示例一,这里promise1是Promise.resolve(promise)执行返回的结果,参数为promise,这时promise1其实就是promise。 - 参数为thenable对象:
thenable对象是指具有then方法的对象,在示例二中Promise.resolve(thenable)传入的参数是thenable对象,此时,该方法会将thenable对象转换为promise对象,然后立即执行then方法。 - 参数为其他对象:
当Promise.resolve(iterable)传入的参数既不是promise实例也不是thenable对象时,该方法会返回一个promise实例,返回值即为传入的iterable。在示例三中,参数传入的是什么,promise实例的返回值就是什么。
1 | // 示例一 |
Promise.reject(reason)
Promise.reject(reason)方法返回一个新的promise实例,实例的状态为rejected,reason为抛出的错误。在下面示例中列出了resolve参数的三种情况,其实每一种都是一样的,的Promise.reject(reason)的参数reason会直接做为错误被捕获。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20var promise = Promise.reject('123');
promise.catch(function(err){
console.log(err); // '123'
});
var thenable = {
then: function(resolve, reject){
reject('123');
}
}
var promise = Promise.reject(thenable);
promise.catch(function(err){
console.log(err); // thenable
});
var promise = Promise.reject();
var promise1 = Promise.reject(promise);
promise1.catch(function(err){
console.log(err); // promise
});