专业英语:
单词 | 释义 |
---|---|
promise | n. 许诺,允诺;希望 |
pending | adj. 未决定的;行将发生的 |
resolve | vi. 解决;决心;分解 |
reject | vt. 拒绝;排斥;抵制;丢弃 |
Promise概述
- Promise主要是用来处理异步任务的。
- 在JS中,promise的含义是“期约”。
- ECMAScript 6中全局环境中新增了引用类型Promise,可以通过new操作符来实例化。创建新期约时需要传入执行器(executor)函数作为参数。
const promise = new Promise(function(resolve, reject) {
// code
})
- 期约对象有两个内部属性,其中
[[PromiseState]]
表示当前状态,[[PromiseResult]]
表示执行结果。
-
期约是一个有状态的对象,可能处于如下三种状态之一:
- 待定(pending):简单的说,在异步操作中,这就表示操作还未结束;
- 兑现(fulfilled/resolved):在异步操作中,这表示操作已经结束,且结果为成功;
- 拒绝(rejected):在异步操作中,这表示操作已经结束,但结果为失败;
-
待定状态可以转化为兑现状态或者拒绝状态,但这个过程是不可逆的,转换过程由用户传入的执行器控制:
new Promise(function(resolve, reject) {
// do something
resolve('hello world'); // 主动调用resolve,将状态转化为兑现(此时它接收一个参数作为执行结果)
})
new Promise(function(resolve, reject) {
// do something
reject('hello world'); // 主动调用reject,将状态转化为拒绝(此时它接收一个参数作为执行结果)
})
- 注意转换是不可逆的,也即转换为兑现或者拒绝后状态就无法再改变:
new Promise(function(resolve, reject) {
// do something
resolve(); // 主动调用resolve,将状态转化为兑现
reject(); // 因为状态已经变成了兑现,所以这里的操作会被静默拒绝(忽略)。
})
Promise.prototype.then()
new Promise(() => {}).then(onResolved, onRejected);
onResolved
也即期约转化为兑现时的回调函数。onRejected
是期约转化为拒绝的回调函数。这两个函数都会被传入一个值,那就是期约的执行结果。- 当执行器主动调用
resolve
转化期约状态后,onResolved就会作为回调函数被调用(注意这里resolve不等于onResolved,他们是不同的)。
new Promise(function(resolve, reject) {
// do something
resolve('hello world'); // 主动调用resolve,将状态转化为兑现
console.log('测试点1');
}).then(result => {
console.log(result);
})
/* 控制台输出:
测试点1
hello wolrd
*/
new Promise(function(resolve, reject) {
// do something
reject('hello world'); // 主动调用reject,将状态转化为兑现
console.log('测试点1');
}).then(null, result => {
console.log(result);
})
/* 控制台输出:
测试点1
hello wolrd
*/
then()
函数不需要Promise实例化后立即调用,可以在任何时候调用then传递处理程序,而如果在你调用then传递参数时,Promise状态已经发生了转化,有了执行结果,那么你传递的处理程序会立即被执行(这很重要);另外,你也可以多次调用then:
const promise = new Promise(function(resolve, reject) {
// do something
resolve('hello world'); // 主动调用reject,将状态转化为兑现
})
setTimeout(function () {
promise.then(result => console.log('测试点1', result))
promise.then(result => console.log('测试点2', result))
}, 1000)
/*
测试点1 hello world
测试点2 hello world
*/
- 此外
then()
函数也是有返回值的,它会返回一个新的Promise实例,该实例具有如下特征:- 当原实例状态为
pending
时,这个新实例的状态也会保持为pending
; - 当原实例状态发生了转化,但我们没有设置对应状态的处理程序(如果状态为resolved,但我们只设置了onRejected,那么也算是未设置处理程序),那么这个新的实例就会使用
Promise.resolve()
(后面会详细说明)基于原有实例的执行结果重构当前状态。 - 在第二种情况下,如果存在对应状态的处理程序,那么新实例就会继续保持
pending
状态,等待处理程序执行完毕并返回结果,然后使用Promise.resolve()
基于该返回值构建新实例。(实际上我也没太弄懂参考书上的描述,结果有点怪异,但从测试结果来看大概是这样的) - 如果原有的Promise实例在执行过程中发送了错误(如状态转化为
reject
但是我们没有设置onRejected
处理函数),那么新实例的状态就会变为rejected
,执行结果就是原本实例的执行结果。
- 当原实例状态为
console.log(
new Promise((resolve, reject) => resolve('resolve')).then(),
new Promise((resolve, reject) => resolve('resolve')).then(result => 'then ' + result),
new Promise((resolve, reject) => resolve('resolve')).then(undefined, result => 'then ' + result)
);
console.log(
new Promise((resolve, reject) => reject('reject')).then(),
new Promise((resolve, reject) => reject('reject')).then(result => 'then ' + result),
new Promise((resolve, reject) => reject('reject')).then(undefined, result => 'then ' + result)
);
new Promise(resolve => resolve('hello')).then().then(result => console.log(result));
// hello
new Promise((resolve, reject) => reject('hello')).then().then(undefined, result => console.log(result));
// hello
new Promise((resolve, reject) => reject('hello'))
.then(result => console.log('test1', result))
.then(undefined, result => console.log('test2', result));
// test2 hello
new Promise((resolve, reject) => resolve('hello'))
.then(result => console.log('test1', result))
.then(result => console.log('test2', result), result => console.log('test3', result));
// test1 hello
// test2 undefined
Promise.resolve()
- 该方法是Promise对象上的方法,而不是原型上的方法,因此不会被继承。
resolve()
方法接收一个参数,然后返回一个Promise实例对象。根据传入参数的不同,返回的Promise实例也会有所区别。
- 传入的参数不是对象类型:返回的实例对象状态为兑现(fulfilled/resolved),且执行结果就是我们传入的参数
- 传入的参数是一个普通对象:结果与第一种情况一样。
console.log(Promise.resolve('hello world'),
Promise.resolve(undefined),
Promise.resolve(null),
Promise.resolve({test: 'hello'}));
const obj = {
then(resolve, reject) {
console.log('then函数被调用');
resolve('hello world');
}
}
Promise.resolve(obj).then(result => console.log('测试点', result));
/*
then函数被调用
测试点 hello world
*/
延迟执行 + 链式调用
- 前不久面试了某大厂的前端实习岗位,其中有一道代码题是让我写出一个
obj.print('start').sleep(3000).print('测试点1').sleep(3000).print('end')
这样的链式调用的(不能使用队列的方式),且可以延迟执行的对象,当时试了半天也没写出来,于是痛并思痛,决定好好研究一下Promise
,现在终于可以轻松搞定了,代码如下:
const timeOutPrint = {
promise: Promise.resolve(),
sleep(time) {
this.promise = this.promise.then(() => new Promise(resolve => setTimeout(resolve, time)))
return this;
},
print(msg) {
this.promise = this.promise.then(() => console.log(msg));
return this;
}
}
timeOutPrint.print('start').sleep(3000).sleep(3000).print('测试点1').sleep(3000).print('end');
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。