Promise
异步编程的一种解决方案,Promise
是一个对象,可以获取异步操作的消息。
两大特点
-
对象的状态不受外界影响。
-
一旦状态改变,就不会再变,任何时候都可以得到这个结果。
三种状态:
- pending(进行中)
- fulfilled(已成功)
- rejected(已失败)
状态改变的两种情况:
- pending 变为 fulfilled
- pending 变为 rejected
resolved:发生上面两种状态其一的时候,状态将不再改变一直保持,称为resolved
语法
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
- 创建一个
promise
实例 promise
构造函数接收一个函数作为参数,该函数的参数为resolve
和reject
两个函数resolve
:将状态从pending 变为 resolved,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。reject
:将状态从 pending 变为 rejected,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。resolve
和reject
在调用的时候带有参数的时候,参数将会返回给回调函数。reject
的参数通常是Error
的对象实例,resolve
的参数除了是一些值以外还可以是函数。resolve
和reject
不会终结Promise
的执行,总是晚于本轮循环的同步任务。Promise
实例生成以后,可以用then
方法分别指定resolved
状态和rejected
状态的回调函数。then
方法接收两个函数作为参数,其中一个在resolved
的时候执行,一个在rejected
的时候执行。在当前脚本所有同步任务执行完才会执行
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then()方法
- promise的实例具有
then
方法,故then
方法其实是定义在原型对象,即Promise.prototype
上的。 then
方法有两个参数,返回的是一个新的Promise实例
,故then
后面可以再调用then
,即链式写法
catch()方法
catch
方法是then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数。
p.then((val) => console.log('fulfilled:', val))
.catch((err) => console.log('rejected', err));
// 等同于
p.then((val) => console.log('fulfilled:', val))
.then(null, (err) => console.log("rejected:", err));
- Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个
catch
语句捕获,catch
返回的还是一个promise
对象,后面可以接着调用then
方法 then
的第二个参数和catch
的区别:catch可以捕捉到前面then中执行中的错误,错误可以一层层的往外抛- 如果没有使用
catch
方法指定错误处理的回调函数,promise
内部的错误不会影响到promise
外部的代码执行 catch
内部还可以再抛出错误,在下一个catch
中捕获
finally()方法
- 指定不管 Promise 对象最后状态如何,都会执行的操作,不接收任何参数
- 总是会返回原来的值
all()方法
- 用于将多个promise实例包装成一个新的promise实例
- 语法:参数具有Iterator接口,返回的每个成员都是promise实例
const p = Promise.all([p1, p2, p3]);
p.then(res => {
//3个子promise执行完才会执行then
console.log(res) //返回的是一个数组,数组内容是3个子promise返回的内容
})
- 状态由参数(p1, p2, p3)的状态决定
a)参数的状态都是fulfilled
,则p的状态也是fulfilled
b)参数中的一个为rejected
,则p的状态也是rejected
,返回的是第一个参数的rejected
实例 - 作为参数的 Promise 实例,自己定义了
catch
方法,那么它一旦被rejected
,并不会触发Promise.all()
的catch
方法。参数的promise实例抛错后执行了自己的catch
方法后会变为fulfilled
。
race()方法
- 用于将多个promise实例包装成一个新的promise实例,这一点同与
all()
方法 - 竞争关系,任何一个子
promise
完成即可触发总Promise回调函数。返回竞争成功的Promise的结果
resolve()方法
将现有对象转为 Promise 对象
- 语法:
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
- 参数的4种情况
a)参数是一个Promise
实例:不做任何修改、原封不动地返回这个实例
b)参数是一个thenable
对象:将这个对象转为 Promise 对象,然后就立即执行thenable对象的then
方法。
【thenable
对象指的是具有then方法的对象】 - 参数不是具有
then
方法的对象,或根本就不是对象:返回一个新的Promise对象,状态为resolved
。
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
//Promise.resolve方法的参数,会同时传给回调函数。
- 不带有任何参数:直接返回一个
resolved
状态的 Promise 对象
reject()方法
返回一个新的 Promise 实例,该实例的状态为rejected
- 语法:
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
// 出错了
Promise.reject()
方法的参数,会原封不动地作为reject
的理由
try()
用promise
处理函数,可以使用then
方法,不区分是同步还是异步,同步的立即执行,异步的等循环结束执行。
方法:
a)用async
函数
b)使用new Promise()
c)使用Promise.try()
方法
当同步方法使用catch
方法时只能捕捉到异步错误,使用Promise.try()
后可以捕捉所有的同步和异步错误
Promise.try(() => database.users.get({id: userId}))
.then(...)
.catch(...)
async
- 作用:处理异步调用
- 返回值是一个
promise
对象,
function fetch() {
return (
fetchData()
.then(() => {
return "done"
});
)
}
//等同于下面的
async function fetch() {
await fetchData()
return "done"
};
await
await的使用是在async
函数体内部
只有await
部分的代码执行完才会接下去执行其他的代码
【本文是学习完阮一峰老师的ES6部分教程自己整理的笔记,原文:http://es6.ruanyifeng.com/#docs/promise 】