1、await
await
操作符用于等待一个 Promise
对象, 它只能在异步函数 async function
内部使用.
await
的使用语法非常简单:
[return_value] = await expression;
其中expression
是一个 Promise
对象或者任何要等待的值;
而 await expression
的执行结果有以下几种情况:
若
expression
是一个Promise
对象, 并且其以值x
被 fulfilled, 则返回值为x
.若
expression
是一个Promise
对象, 并且其以异常e
被 rejected, 则抛出异常e
.若
expression
不是Promise
对象, 则会将expression
处理成一个以expression
值被 fulfilled 的Promise
对象, 然后返回这个Promise
对象的最终值 (即 expression 值). 这种用法没太大意义, 因此实际使用时还是尽量在 await 后跟一个Promise
对象.
2、async
使用 async function
可以定义一个 异步函数,语法为:
async function name([param[, param[, ... param]]]) {
statements
}
async
函数的返回值很特殊: 不管在函数体内 return
了什么值, async
函数的实际返回值总是一个 Promise
对象. 详细讲就是:
若在 async
函数中 return
了一个值 x
, 不管 x
值是什么类型, async
函数的实际返回值总是 Promise.resolve(x)
.
3、Promise
所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
两个特点
对象的状态不受外界影响。
Promise
对象代表一个异步操作,有三种状态:Pending
(进行中)、Resolved
(已完成,又称Fulfilled
)和Rejected
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise
对象的状态改变,只有两种可能:从Pending
变为Resolved
和从Pending
变为Rejected
。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise
对象添加回调函数,也会立即得到这个结果。这与事件(Event
)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
优点:
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
缺点:
Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
三种状态:
- pending :进行中
- fulfilled:已经成功
- rejected:已经失败
两种状态改变:
从pending变为fulfilled:Promise.resolve(value)
resolve
函数的作用是,将Promise
对象的状态从“未完成”变为“成功”(即从pending
变为resolved
),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;从pending变为rejected:Promise.reject(value)
reject
函数的作用是,将Promise
对象的状态从“未完成”变为“失败”(即从pending
变为rejected
),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
这两种方法都是返回一个以给定值解析后的Promise
对象。但如果这个值是个thenable
(即带有then
方法),返回的promise
会“跟随”这个thenable
的对象,采用它的最终状态(指resolved
/rejected
/pending
/settled
);否则以该值为成功状态返回promise
对象。
Promise
实例生成以后,可以用then
方法分别指定resolved
状态和rejected
状态的回调函数。
promise.then(function(value){
//success
},function(error){
//failure
});
两种状态改变:
举栗子
function test(resolve, reject) {
var timeOut = Math.random() * 2;
log('set timeout to: ' + timeOut + ' seconds.');
setTimeout(function () {
if (timeOut < 1) {
log('call resolve()...');
resolve('200 OK');
}
else {
log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}
}, timeOut * 1000);
}
这个test()
函数有两个参数,这两个参数都是函数,如果执行成功,我们将调用resolve('200 OK')
,如果执行失败,我们将调用reject('timeout in ' + timeOut + ' seconds.')
。可以看出,test()
函数只关心自身的逻辑,并不关心具体的resolve
和reject
将如何处理结果。
有了执行函数,我们就可以用一个Promise对象来执行它,并在将来某个时刻获得成功或失败的结果:
var p1 = new Promise(test);
var p2 = p1.then(function (result) {
console.log('成功:' + result);
});
var p3 = p2.catch(function (reason) {
console.log('失败:' + reason);
});
变量p1
是一个Promise
对象,它负责执行test
函数。由于test
函数在内部是异步执行的,当test
函数执行成功时,我们告诉Promise
对象:成功时执行then
,失败时执行catch
。
可以串联起来,所以上述代码可以简化为:
new Promise(test).then(function (result) {
console.log('成功:' + result);
}).catch(function (reason) {
console.log('失败:' + reason);
});