JS Promise对象
Promise 的介绍
什么是 Promise 对象
Promise
对象对 异步操作 进行了封装,并提供统一的 API 访问异步的结果。
Promise
对象是一个构造函数,用于创建Promise实例。
为什么需要 Promise 对象
JavaScript是一种单线程脚本,当需要进行异步操作时,往往要通过 传入回调函数 的方式。这种方式并没有什么技术上的缺陷,唯一的痛点在于:不利于代码的阅读和理解,毕竟人的思维是线性的。
举个例子:
当需要按序调用多个异步请求,并且下一个异步请求依赖上一个异步返回的结果,代码是长这样的:
/*
* 假设requestA,requestB,requestC,...这些函数内部都调用了异步方法,例:
* function requestX(callback){
// 使用setTimeout()模拟异步请求
setTimeout(function(){
var result = null;
*
* do Something and get result
*
callback(result);
})
}
*/
requestA(function(resultA){
//...doSomething
requestB(resultA, function(resultB){
//...doSomething
requestC(resultB, function(resultC){
//...doSomething
requestD(...)
})
})
})
这种层层包裹的代码非常不利于阅读,现在有了 Promise 的概念,我们可以将这种 不友好的层级嵌套 转换为 符合我们思维模式的 链式连接:
/*
*
*假设requestA,requestB,requestC,...这些函数返回了Promise实例,例:
* function requestX(){
return new Promise(function(resolve, reject){
// 使用setTimeout()模拟异步请求
setTimeout(function(){
var result = null;
*
* do Something and get result
*
resolve(result);
})
})
}
*
*/
requestA()
.then(function(resultA){
//...doSomething
return requestB(resultA)
})
.then(function(resultB){
//...doSomething
return requestC(resultB)
})
.then(function(resultC){
//...doSomething
return requestD(resultC)
})
Promise
对象改进了JavaScript异步编程的方式。虽然它很早就被使用,但直到 ES2015
的发布才正式将它纳入ECMAScript的标准中。
Promise 的三种状态
Promise
实例有三种状态:
pending
:表示异步操作未完成。fulfilled
:表示异步操作成功。reject
:表示异步操作失败。
另外需要注意的一点:这三种状态的改变只能是 pending -> fulfilled
或 pending -> reject
其中一种,并且状态的改变是不可逆的。
当Promise实例的状态发生改变时,可以通过实例的then()
方法来接收 Promise 传递出来的值。
创建 Promise 实例
前面我们提到, Promise 是一个构造函数。所以实例是通过 new Promise(...)
来创建的:
function callback(resolve, reject){
// 异步代码...
}
// 创建 Promise 实例
var p = new Promise(callback);
Promise
构造函数 接收一个 回调函数callback
作为参数,这个 callback
回调函数通常用于执行异步操作的代码。Promise会给这个 callback
回调函数传入两个特殊的参数:
- resolve函数:将
Promise
实例的状态由pending -> fulfilled
- reject函数:将
Promise
实例的状态由pending -> reject
这两个函数参数一般在异步代码的回调中调用。
注意:Promise实例一旦生成,会立即执行callback内部的代码。为了能在合适的时候使用它,通过我们把它放入函数中:function createPms(){ return new Promise(...)}
Promise 属性列表
属性 | 值 | 描述 |
---|---|---|
length | 1 | 表示Promise构造函数可传入参数的个数。 |
prototype | Object | 指向Promise实例的原型。什么是原型 |
all() | Object | Promise.all() 将多个 Promise 实例,包装成一个新的Promise 实例,并返回。当所有传入的实例状态都变成fulfilled 时,返回的实例状态才变成fulfilled 。传入的实例只要有一个变成reject ,返回的实例状态就变成reject 。 |
race() | Object | Promise.race() 将多个 Promise 实例,包装成一个新的 Promise实例,并返回。传入的实例中,只要有一个状态率先改变状态,返回的实例则跟着改变状态。 |
reject() | Object | Promise.reject() 返回一个状态为 rejected 的 Promise 实例。 |
resolve() | Object | Promise.resolve() 返回一个状态为 resolve Promise 实例。 |
Promise实例属性列表
属性 | 返回值 | 描述 |
---|---|---|
Promise.prototype.constructor | Object | 指向实例的构造函数,即 Promise 对象。 |
Promise.prototype.catch() | Object | 该方法为Promise 实例添加状态改变为 reject 时的回调函数,并返回一个新的 Promise 实例。 |
Promise.prototype.then() | Object | 该方法为 Promise 实例添加状态改变时的回调函数,并返回一个新的 Promise 实例。 |
Promise.prototype.finally() | Object | 该方法为 Promise 实例指定不管对象最后状态如何,都会执行的回调函数。 |
Promise实现异步编程的完整示例
// 编写一个赌大小的功能模块,一秒钟后随机生成一个0 - 1的小数,大于0.5代表大(胜出),小于等于0.5代表小(落败)。
function gambling(){
return new Promise((resolve, reject) => {
setTimeout(() => {
let n = Math.random();
n > 0.5 ? resolve(n) : reject(n);
}, 1000);
})
}
// 现在开始赌博游戏
gambling().then(n => {
alert(`胜出,promise实例输出的值为:${n}`)
}, v => {
alert(`落败,promise实例输出的值为:${n}`)
})
/*运行输出结果(输出结果是随机的,这里的结果仅作参考):
* 胜出,promise实例输出的值为:0.7762996702761356
* */
在上面的实例中:
gambling()
函数返回了一个Promise实例。这个实例内部封装了一个异步任务:在一秒后生成一个随机值,通过这个随机值来决定Promise实例的状态。
Promise内部提供了两个函数(resolve, reject)用于改变Promise实例的状态,并
then()方法是Promise标准提供的一个接口,用于获取promise实例传出来的值。