在 《Puppteer 实现 web 自动测试》 一文里,可以看出来如果 Puppteer 脚本用 async/await 和 promise的一些写法,会让脚本非常易懂,而且符合我们人工操作浏览器的习惯。所以为了写好 Puppteer 脚本,需要先对 async/await 的概念有所了解。
一个比方
你和老王打赌:明天是否下雨。如果你赢了,老王给你10个亿;如果你输了,你给老王10块钱。
如果用一块展板描述这个赌局,可以是这样:
【明日下雨】 老王赌局
——————————
赢: +10亿
输: –10元
转眼跟小王打赌:
【明日下雨】 小王赌局
——————————
赢: 被请KFC
输: 请KFC
由上可见, 赌局 和 赌注 是无关的。比如,同样是明天下雨,另一场赌局可能如下:
由此得到【规则1】
- 规则1:输赢规则和赌注无关,可以分离
当赌局完成后,只要出现了一种情况,那么另一种情况必然不会同时发生,比如不可能既下雨又不下雨。由此得到【规则2】
- 规则2:只能有一种结果出现。
如果你和老王商量好了:如果明天下雨,老王付你10块钱。到了第二天果然下雨,老王反悔了,想修改输赢规则,你一定是不同意的,这就叫买定离手。由此得到【规则3】
- 规则3:输赢结果一旦出现,则不能更改。
如何描述
用一段伪代码描述上面的下雨赌局,可以这么写
赌局(赢,输){
到明天()
如果下雨{
赢()
}如果没下{
输()
}
}
到明天 函数
可以替换成 抛硬币()
, 或者是
参加考试()
,这种负责产生结果的函数,可以称之为"生产者"。
赢 函数
可以是 {得5元}
,或者是
{被请KFC}
,这种针对结果的处理方案,可以称之为"消费者"。
这种"生产者"和"消费者"分离的状态,对应了上面的 规则 1
而赌局本身,既不产生结果,也不消费结果,只是将无关的二者结合在一起,并进行一次。将赌局抽象出来,就是 Promise 。
生产者(抛硬币)→ Promise → 消费者(赌注)
所以 Promise 可以理解为一个中介(Proxy),一个 Promise 对象用下面代码生成:
let promise = new Promise(function(resolve, reject) {
// 生产者代码
});
当 promise
对象生成时,将执行 生产者代码,并生产出结果。Promise 接收一个函数作为参数,这个函数的两个参数分别对应成功和失败的消费者函数,消费前面生产出的结果。
生产者代码在得出结果后,应该根据结果的不同,调用对应的消费者函数(成功则调用 resolve,失败则调用 reject),同时将结果作为消费者函数的参数,从 promise
对象中传递出去。
举个例子,最简单的生产者代码,恐怕就是"什么也不做"了,直接判定为成功,只有resolve一种结果。
let promise = new Promise(function(resolve, reject) {
resolve("done")
});
这段代码执行后,对象 promise
的状态就固定为成功(fulfilled),而且不能改变。当然也可以直接判定失败:
let promise = new Promise(function(resolve, reject) {
reject("lose")
});
这段代码执行后,对象 promise
的状态就固定为失败(rejected)
Await
生产者代码除了生产成功或者失败的结果,往往还有其他类型的结果输出,比如文件内容、或者新的对象实例,等等。所以需要通过
resolve 函数将输出的结果传递出来。 await
可以在外面接纳这个结果。
Promise → resolve → await
比如,可以这么使用 await
:
let promise = new Promise(function(resolve, reject) {
resolve("done")
});
let result = await promise;
console.log(result); // "done"
这个例子里,我们可以从控制台里看到 “done” 的输出, await
一直等待
promise 的成功结果,一旦等到,就将 resolve
的参数返回给 result
变量
Async
要想使用 await
关键字,还必须声明 await
所在的函数为
async
,用法很简单,只要在 function
前面加上 async
就行。
async function(){ await … }
async function(){
let promise = new Promise(function(resolve, reject) {
resolve("done")
});
let result = await promise;
console.log(result); // "done"
}
函数声明之前加上 async
后, 即使不用明确的声明 return,函数总会隐含的返回一个 Promise。如果明确的写明 return
一个值,函数也仍然返回一个 Promise,然后使这个 Promise 成功 resolve 那个值。比如下面的例子:
async function(){
//其他代码
return 1
}
等效于
async function(){
//其他代码
return Promise.resolve(1)
}
这个返回值是可以被 await 等待得到的。
理解了上面的内容,我们就可以继续用 puppeteer 编写自动脚本了
如果您对本文有疑问或者寻求合作,欢迎 联系邮箱 。邮箱已到剪贴板
精彩评论
本站 是个人网站,采用 署名协议 CC-BY-NC 授权。
欢迎转载,请保留原文链接 https://www.lfhacks.com/tech/understanding-promise/ ,且不得用于商业用途。