Promise
基本概念:
promise是es6中提出的一种异步编程的解决方案。
- promise有三种状态,pending,fulfilled,rejected。promise的状态不受外部的影响,只有内部的异步操作的结果可以影响promise的状态。其他手段无法影响promise的状态
- promise的状态一旦改变就无法更改了。并且状态的变化只有两种可能。pending->fulfilled和pending->rejected。
promise的优点:
promise可以将异步操作用同步的流程表达出来,避免的回调地狱,是代码更可控,更易读。
promise的缺点:
- promise对象一旦建立就会立刻执行,无法取消。
- 当promise处于pending状态时,无法得知进展到哪一个阶段
promise基本用法
promise是一个构造函数,可以通过new生成一个promise实例
promise构造函数接受一个函数作为参数,该函数有两个参数(resolve,reject),也都是函数。这两个函数时js引擎提供的,不需要自己写。
resolve和reject函数
resolve的作用是,将promise对象的状态从pending转为fulfilled,在异步操作执行成功时调用,并将异步操作的结果作为参数,返回出去。
reject的作用是,将promise的状态从pending转为rejected,在异步操作失败时调用,并将异步操作的错误作为参数,返回出去
注:调用resolve或者reject并不能中介promise的参数函数执行
new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
// 2 resolve后边的console.log(2)仍然会执行
// 1
一般来说resolve以后promise的使命就结束了,因此可以使用 return来保证resolve或者reject就是promise 内最后执行的语句。
then方法和catch方法都是定义在promise的原型对象上边
then方法
promise对象可以用then方法分别指定promise对象的状态为fulfilled和rejected的回调函数。
then方法可以接受两个回调函数作为参数,第一个函数是promise对象的状态转为fulfilled时调用,第二个函数是promise对象的状态转为rejected时调用。这两个函数都是可选参数,不一定要提供。并且这两个函数都可以接受promise传出的值作为参数(创建promise对象的时候,resolve函数和reject函数传出来的值)。
then同时会返回一个新的promise对象,这也是promise实现链式调用,解决回调地狱的原因。
catch方法
catch方法是then(null,rejection)和then(undefined,rejection)的别名,用于指定发生错误时的回调函数。相对于then的第二个函数,更加推荐使用catch的使用。
注:如果没有使用catch作为发生错误时的回调函数,promise内部的错误也不会影响外部的代码
js语言遇到错误的时候,会退出进程,终止脚本运行
console.log(abc+2);//Uncaught ReferenceError: abc is not defined
console.log(1);
但是如果promise内部出现了错误,promise会“吃掉”错误,不会退出进程,终止脚本。
const p1 = new Promise((resolve,reject)=>{
resolve(x+2)
})
setTimeout(() => {
console.log(3);
}, 0);
console.log(1); //控制台输出:1, 2, Uncaught (in promise) setTimeout(() => { ReferenceError: x is not defined
console.log(4); 3,4
}, 0);
console.log(2);
我们可以注意到即使promise报错了,后续的log都可以执行
Promise.prototype.finally()
用于指定promise对象无论状态是什么,最后都要执行的方法,示例代码:
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
Promise.all()
将多个promise实例对象包装成一个全新的promise实例。
const p = Promise.all([p1, p2, p3]);
promise.all的参数可以是数组或者具有iterator接口的参数
p的状态是由参数里的promise决定的。
- 只有参数中的promise实例全部为fulfilled时,promise.all返回的promise实例的状态才会是fulfilled
- 只要参数中的promise实例有一个为rejected,那么promise.all返回的promise实例的状态就为rejected,并且第一个被rejected的实例的返回值,会传递给promise.all返回的promise实例。
Promise.race()
promise.race()方法同样是将多个promise实例对象,包装成一个新的promise实例。
const p = Promise.race([p1, p2, p3]);
promise.race()和promise.all()大体上相同,只是race()返回的promise实例的状态是由参数里第一个改变状态的promise对象决定的。
Promise.resolve()
将现有对象转换为promise对象,promise.resolve()起到的就是这个作用。
Promise.resolve('foo')<========> new Promise(resolve=>{resolve('foo')})
注:当Promise.resolve()中不传递参数或者参数不具备then()方法的对象的时候,那么会立刻返回一个状态为resolved的promise实例对象,这个过程是同步的。并且将紧跟着的then方法放到微任务队列当中。然后执行下一段同步代码
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)
});
// 出错了
\