异步编程——微信小程序

1. 前言

引用来自:微信小程序开发中的多线程处理与异步编程_微信小程序 多线程-CSDN博客

微信小程序是基于JavaScript开发的,与浏览器JavaScript不同,小程序运行在WebView内部,没有多线程的概念。小程序的 JavaScript 是单线程的,也就是说它只有一个主线程来处理所有的任务,包括用户交互、网络请求、动画等。但是,为了提高性能,小程序提供了一些异步编程的方法,比如使用 Promise、async/await 来处理网络请求和其他异步操作。

2. 异步编程的实现

2.1 Promise

参考:JavaScript Promise | 菜鸟教程

Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。

Promise 构造函数接受一个函数作为参数 ,该函数是同步的并且会被立即执行,所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject,分别表示 Promise 成功和失败的状态。

起始函数执行成功时,它应该调用 resolve 函数并传递成功的结果。当起始函数执行失败时,它应该调用 reject 函数并传递失败的原因。

Promise 构造函数返回一个 Promise 对象,该对象具有以下几个方法:

  • then:用于处理 Promise 成功状态的回调函数。
  • catch:用于处理 Promise 失败状态的回调函数。
  • finally:无论 Promise 是成功还是失败,都会执行的回调函数

2.1.1 示例1 Promise返回成功状态

先以Promise返回成功状态为例,先执行"起始函数",由于返回成功状态(即使用resolve),会再执行then,再执行finally。

复制代码
onButton1Clicked(){
        const promise = new Promise((resolve,reject)=>{
            setTimeout(()=>{
                console.log("1秒-第一次打印");
                resolve();
            },1000)
        });
        promise.then(()=>{
            console.log("成功")
            setTimeout(()=>{
                console.log("2秒-第二次打印");
            },2000)
        }).finally(()=>{
            console.log("最后")
        });
    },

打印结果:

我好奇:then是成功才会调用的函数,finally无论成功失败都会调用,那谁先谁后呢?测试发现谁写前面先调用谁,比如我这样写:

复制代码
promise.finally(...).then();

打印结果是这样的:

不过菜鸟教程中说不建议这样写,建议:最好按 then-catch-finally 的顺序

Q: then、catch 和 finally 序列能否顺序颠倒?

A: 可以,效果完全一样。但不建议这样做,最好按 then-catch-finally 的顺序编写程序。

2.1.2 示例2 Promise 与网络请求wx.request 结合使用

复制代码
    onReqAuth() {
        const request = new Promise((resolve, reject) => {
            wx.request({
                url: 'https://www.yourhost.cn/api/',
                data: {
                    sbxh: 'S20230831-001',
                    ident: 'T01',
                    parm: ''
                },
                method: 'POST',
                success: (res) => {
                    resolve(res.data);
                },
                fail: (err) => {
                    reject(err)
                }
            })
        });
        request.then((data) => {
            console.log('请求成功', data);
            // decodeURIComponent:解析URL编码
            let msg = decodeURIComponent(data.msg);
            console.log(msg);
            this.data.reqResult = msg;
            this.setData({
                reqResult: this.data.reqResult
            })
        }).catch((err) => {
            console.error('请求失败:', err);
        })

    },

2.1.3 示例3 then传递值给下一个then

这个示例完全照搬菜鸟教程,

resolve() 中可以放置一个参数用于向下一个 then 传递一个值,then 中的函数也可以返回一个值传递给 then。但是,如果 then 中返回的是一个 Promise 对象,那么下一个 then 将相当于对这个返回的 Promise 进行操作,这一点从刚才的计时器的例子中可以看出来。

复制代码
new Promise(function (resolve, reject) {
    console.log(1111);
    resolve(2222);
}).then(function (value) {
    console.log(value);
    return 3333;
}).then(function (value) {
    console.log(value);
    throw "An error";
}).catch(function (err) {
    console.log(err);
});

注意:

  • resolve 和 reject 的作用域只有起始函数,不包括 then 以及其他序列;
  • resolve 和 reject 并不能够使起始函数停止运行,别忘了 return。

++resolve 和 reject 并不能够使起始函数停止运行++,这个我是这样理解的:在起始函数内调用resolve 或 reject 不代表起始函数结束了,它会继续执行后面的语句,直到函数结束;然后在起始函数执行完毕后,再去执行对应的成功或失败后需要操作。比如在示例1的resolve后增加打印,将会打印如下:

2.2 async/await

5.3 ES6 async 函数 | 菜鸟教程

2.2.1 async 异步关键词

async 是 ES7 才有的与异步操作有关的关键字。

async 函数返回一个 Promise 对象 ,可以使用then方法添加回调函数。

复制代码
async function testAsync(){
    return "testAsync";
}

onButton1Clicked(){
    console.log(testAsync());
    testAsync().then(v =>{
       console.log(v);
    })
}

2.2.2 await 操作符

async 函数中可能会有 await 表达式,async 函数执行时,如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,恢复 async 函数的执行并返回解析值。

await 关键字仅在 async function 中有效。

复制代码
function testAwait(){
    return new Promise((resolve,reject)=>{
        console.log("testAwait");
        setTimeout(()=>{
            console.log("setTimeout");
            resolve();
        },1000);
    });
}

async function helloASync(){
    await testAwait();
    console.log("helloASync")
}


helloASync();

正常情况下,await 命令后面是一个 Promise 对象,它也可以跟其他值,如字符串,布尔值,数值以及普通函数。

复制代码
function testAwait(){
   console.log("testAwait");
}
async function helloAsync(){
   await testAwait();
   console.log("helloAsync");
}
helloAsync();
// testAwait
// helloAsync

await针对所跟不同表达式的处理方式:

  • Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。
  • 非 Promise 对象:直接返回对应的值。
相关推荐
moxiaoran57532 小时前
uni-app学习笔记二十九--数据缓存
笔记·学习·uni-app
pop_xiaoli4 小时前
OC—UI学习-2
学习·ui·ios
Lin Hsüeh-ch'in4 小时前
Vue 学习路线图(从零到实战)
前端·vue.js·学习
恰薯条的屑海鸥5 小时前
零基础在实践中学习网络安全-皮卡丘靶场(第十五期-URL重定向模块)
学习·安全·web安全·渗透测试·网络安全学习
自小吃多5 小时前
STC8H系列 驱动步进电机
笔记·单片机
moxiaoran57537 小时前
uni-app学习笔记三十--request网络请求传参
笔记·学习·uni-app
嘉陵妹妹7 小时前
深度优先算法学习
学习·算法·深度优先
乖乖是干饭王8 小时前
Linux系统编程中的_GNU_SOURCE宏
linux·运维·c语言·学习·gnu
待什么青丝9 小时前
【TMS570LC4357】之相关驱动开发学习记录2
c语言·arm开发·驱动开发·单片机·学习
行云流水剑9 小时前
【学习记录】如何使用 Python 提取 PDF 文件中的内容
python·学习·pdf