【小程序】007 Promise与Async/Await

网友投稿 602 2022-05-30

Promise 是一个 ECMAScript 6 提供的类,

Async/await 是 ECMAScript 7 新增的内容,

两者目的都是为了更加优雅地书写复杂的异步任务。

此处介绍她们关于后面小程序开发所需要主要内容,更为详细内容请参考手册、文档。

我们都知道JS是一个单线程的语言,一次只能执行一个任务,如果碰到时间较长任务,会被拖到任务队列等待其他任务完成后再执行。但是类似于向后台请求数据操作,后面的数据处理任务依赖于请求数据的完整性,由于网络情况、服务端数据处理能力,数据包大小,可能并未得到完整数据就执行了后面的数据处理任务,出现意想不到的结果。为了保证数据获取的完整性,有必要使用异步操作。

回调地狱

如果需要多次调用异步函数,例如,如果我想分三次输出字符串,第一次间隔 1 秒,第二次间隔 2 秒,第三次间隔 3 秒:

setTimeout(function () { console.log("First"); setTimeout(function () { console.log("Second"); setTimeout(function () { console.log("Third"); }, 3000); }, 2000); }, 1000);

如果调用嵌套的增加,代码层次变得更深,无论是维护还是异常处理难度也随之增加,尤其是我们使用的是可能包含了很多循环和条件语句的真实代码。这些容易使人迷茫的异步回调编写方式被称为“回调地狱”或“厄运金字塔”。

而Promise可以通过使每个行为都成为一个独立的函数来尝试减轻这种问题

Promise

Promise 对象的构造器(constructor)语法如下:

let promise = new Promise(function(resolve, reject) { // executor });

【小程序】007 Promise与Async/Await

传递给 new Promise 的函数被称为 executor。当 new Promise 被创建,executor 会自动运行。

它的参数 resolve 和 reject 是由 JavaScript 自身提供的回调。我们的代码仅在 executor 的内部。

当 executor 获得了结果,无论是早还是晚都没关系,它应该调用以下回调之一:

resolve(value) — 如果任务成功完成并带有结果 value。

reject(error) — 如果出现了 error,error 即为 error 对象。

所以总结一下就是:executor 会自动运行并尝试执行一项工作。尝试结束后,如果成功则调用 resolve,如果出现 error 则调用 reject。

由 new Promise 构造器返回的 promise 对象具有以下内部属性:

Promise有三种状态state

最初是 "pending",然后在 resolve 被调用时变为 "fulfilled",或者在 reject 被调用时变为 "rejected"。

三种事件状态由"pending"变为 "fulfilled"或"rejected"后不可倒流回"pending"状态

比如:学校要举行期末考试,等待考试状态是"pending",成功开展考试变是 "fulfilled",由于疫情原因小伙伴们提前撤退没有参与考试是"rejected",都不再回到等待考试状态。

每一种状态会对应result结果

result 最初是 undefined,然后在 resolve(value) 被调用时变为 value,或者在 reject(error) 被调用时变为 error。

等待时undefined,成功开展考试可以得到各个学生的试卷内容resolve(value),或者没能举办考试得到开展失败reject(error)的记录

所以,executor 最终将 promise 移至以下状态之一:

Promise.all()与Promise.race()

Promise.all()

微信发朋友圈时,想上传9张图片到云存储,类似这种等待所有事件完成再执行后续操作一般使用Promise.all()

以下是对成功 fulfulled 的 promise 使用.then做出的反应:

setTimeout(code/function, milliseconds, param1, param2, ...)用于在指定的毫秒数后调用函数或计算表达式。

Promise.all()会等待数组里面所有promise的executor 运行完毕后再以.then()处理

例如,以下是对失败 rejected 的 promise 使用.catch做出的反应:

Promise.all()会等待数组里面所有promise的executor 运行一旦执行reolve()回调则认为事物失败,再以.catch()处理,且脚b本程序可继续执行。

Promise.race()

Promise.race()[p1,p2])只要有一个请求完成就会触发后面.then(),

常用于判断请求是否超时

比如p1事件,p2是个定时器,如果先执行p2,就可以知道p1超时了,该做些其他操作。

Async/Await

在云函数里,由于 Node 版本最低是 8.9,因此是天然支持 async/await 语法的。而在小程序旧版本则不然。

两种方式解决:

①直接改变基础库环境,到新版本

②配置相关工具,需要下载并引入额外的文件。可把这个 regenerator/runtime.js 文件引用到有使用 async/await 的文件当中。手动import regeneratorRuntime

https://gitee.com/longyorke/miniprogram_async_await/tree/master/

Async

在函数前面的 “async” 这个单词表达了一个简单的事情:即这个函数总是返回一个 promise。其他值将自动被包装在一个 resolved 的 promise 中。

下面这个函数返回一个结果为1的 resolved promise,

async function f() { return 1; } f().then(alert); // 1

等效于

async function f() { return Promise.resolve(1); } f().then(alert); // 1

Await

关键字 await 让 JavaScript 引擎等待直到 promise 完成(settle)并返回结果。

只在 async 函数内工作

(async () => { await this.example(); })()

这里的例子就是一个 1 秒后 resolve 的 promise,alert的内容需要等待完整的信息传入:

async function f() { let promise = new Promise((resolve, reject) => { setTimeout(() => resolve("done!"), 1000) }); let result = await promise; // 等待,直到 promise resolve alert(result); // "done!" } f();

await 使得不会进行后面依赖函数的执行,直到 promise 状态变为 settled,然后以 promise 的结果继续执行。

在page.js中我们一般把函数定义放在钩子回调函数同层级下,在生命周期函数里面执行

onLoad: function (options) { console.log(this.example()) }, async example(){ console.log("example") return 1 },

相比于 promise.then,它只是获取 promise 的结果的一个更优雅的语法,同时也更易于读写。

async/await 可以和 Promise.all 一起使用

// 等待结果数组 let results = await Promise.all([ require(url1), require(url2), ... ]);

如果出现 error,也会正常传递,从失败了的 promise 传到Promise.all,然后变成我们能通过使用try..catch在调用周围捕获到的异常(exception)。

使用try..catch,如果有 error 发生,执行控制权马上就会被移交至catch块。

async function f() { try { const rp = require("request-promise") let response = await rp('/no-user-here'); let user = await response .json(); } catch(err) { // 捕获到 rp和 response.json 中的错误 alert(err); } } f();

如果我们没有try..catch,发生错误后,那么由异步函数f()的调用生成的 promise 状态为 rejected。我们可以在函数调用后面添加.catch来处理这个 error:

async function f() { const rp = require("request-promise") let response = await rp('/no-user-here'); } // f() 变成了一个 rejected 的 promise f().catch(alert); // TypeError: failed to fetch // (*)

async/await是基于 promise 的,因此我们可以同时使用promise.then/catch与async/await

async await JavaScript Promise 小程序

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:C语言与C++学习路线和资料
下一篇:【F#从入门到实战】11. F#库FParsec入门
相关文章