由于JavaScript的语言特性:
- 单线程(single threaded)
- 同步执行(Synchronously executed)
但在有的时候需要JavaScript进行异步执行代码,ES6给出的解决方法是Promise。
Promise的基本介绍:
promise翻译成中文有‘承诺’的意思,意思给你一个承诺,后期可能会实现承诺也可能会没用实现承诺。
promise有三种状态:
- 待定( pending ) : 初始状态,既没有被兑现,也没有被拒绝
- 已实现( resolve / fulfilled ) : 意味着操作已经完成
- 已拒绝 (rejected):意味着操作失败
从图中我们可以清楚的看出 promise 三种状态之间的关系:
成功 ( reslove ) ⇒ 调用
resolve
, 会执行Promise对象的then方法传入回调函数失败 ( rejected ) ⇒ 调用
reject
, 会执行Promise对象的catch方法传入回调函数
Promise 的状态一旦被确定下来,无法被更改,resolve、reject两个函数不会代码禁止向下执行,为了防止继续向下执行,所以要加上return。
Promise的then/catch方法:
promise 中有then()
方法,返回一个 promise
。接受两个参数:Promise 的成功(reslove
)和失败(reject
)情况的回调函数。
const p = new Promise()
p.then(data => {
// resolve dosomething
}, err => {
// reject dosomething
});
也可以写作:
promise.((resolve, reject)=>{
// resolve(data) 或者 reject(err)
// dosomething
})
又由于then和catch方法都会返回 promise,所以 promise 可以被链式调用
链式调用
Promise 实现了链式调用,也就是说每次调用 then
之后返回的都是一个 Promise,并且是一个全新的 Promise,原因也是因为状态不可变。如果你在 then 中 使用了 return,那么 return 的值会被 Promise.resolve()或者Promise.reject() 包装
Promise.resolve(1)
.then(res => {
console.log(res) // => 1
return 2 // 包装成 Promise.resolve(2)
})
.then(res => {
console.log(res) // => 2
})
举一个小例子
function foo(url) {
return new Promise((resolve, reject) => {
// 假设这是网络请求,需要请求完毕才能返回给用户使用
setTimeout(() => {
if (url === 'success') {
resolve({ code: '200', message: '请求成功' })
}
if (url === 'failure') {
reject({ code: '-200', message: '请求失败' })
}
}, 1000)
}).then(data => {
console.log(data);
}).catch(err => {
console.log(err);
})
}
foo('success')
foo('failure')
当foo()函数传入的是success
值时,pedding状态转化为fullfill,会调用resolve
执行Promise对象的then方法传入回调函数,最后打印出{ code: '200', message: '请求成功' }
当foo()函数传入的是failure
值时,pedding状态转化为reject,会调用resolve
执行Promise对象的catch方法传入回调函数,最后打印出{ code: '-200', message: '请求失败' }