上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

[油猴脚本开发指南]包装异步代码为同步代码

[复制链接]

123

主题

932

帖子

550

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
550
发表于 2021-8-23 01:29:27 | 显示全部楼层 | 阅读模式

前言

这节课我们学习如何将一段异步代码包装成同步代码

异步代码

function GetMess(){
        GM_xmlhttpRequest({
        url:"https://bbs.tampermonkey.net.cn/",
        method :"GET",
        headers: {
        },
        onload:function(xhr){
            console.log(xhr.responseText);
        }
    });
}
GetMess()

这是一段十分简单的代码,在函数内使用了一个get获取网页内容,如果我们想在获取内容之后进行一些处理需要写在onload函数内,这种代码就叫做异步代码,当执行完请求后再回调处理的函数,有时候这样非常麻烦,那有没有什么办法改为同步代码呢?解决方案就是使用Promise

    let p=new Promise((resolve, reject) => {

    })

我们首先创建一个Promise,当Promise不调用resolve和reject结束状态,那将一直是pengding状态,只有调用resolve或reject的时候,才可以结束状态并返回resolve或reject函数内的值

function GetMess(){
    let p=new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            url:"https://bbs.tampermonkey.net.cn/",
            method :"GET",
            headers: {
            },
            onload:function(xhr){
                resolve(xhr.responseText)

            }
        });
    })
}
GetMess()

现在我们要求在onload后使用resolve结束这个Promise状态,并返回xhr.responseText的值

我们再结合async和await的语法糖就可以了

await需要一个Promise,所以我们需要将我们构建的这个Promise返回

function GetMess(){
    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            url:"https://bbs.tampermonkey.net.cn/",
            method :"GET",
            headers: {
            },
            onload:function(xhr){
                resolve(xhr.responseText)

            }
        });
    })
}
async function GetPromiseAndWait(){
   let text=await GetMess()
}
GetPromiseAndWait()

添加await GetMess()后,GetMess函数会返回一个Promise,Async和Await语法糖会使Promise阻塞直至完成状态后,将resolve内填入的值赋值给text变量上。

需要注意的是我们不可以在全局作用域内使用await,目前并未实现该特性,只有在async的函数内才可以使用await。

由于GetPromiseAndWait使用了Async语法糖,所以调用他现在也会返回一个Promise变量,如果我们想要同步获取他返回的值,也需要使用Async与Await

function GetMess(){
    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            url:"https://bbs.tampermonkey.net.cn/",
            method :"GET",
            headers: {
            },
            onload:function(xhr){
                resolve(xhr.responseText)

            }
        });
    })
}
async function GetPromiseAndWait(){
   let text=await GetMess()
   return '我处理完了'
}
function WantGetFinallyText(){
    let data=GetPromiseAndWait()
    console.log('WantGetFinallyText',data)
}

WantGetFinallyText()

图片.png

我们可以看到console.log输出了一个promise,这个值是pengding,因为我们调用了GetPromiseAndWait,他在没有执行到return的时候是一个执行中的状态。

如果我们想要获取到GetPromiseAndWait的值,需要让这个函数执行到return,也就是fulfilled状态。这个时候我们需要对调用这个函数返回的Promise再进行一个Async和Await,来让这个Promise形成阻塞

function GetMess(){
    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            url:"https://bbs.tampermonkey.net.cn/",
            method :"GET",
            headers: {
            },
            onload:function(xhr){
                resolve(xhr.responseText)

            }
        });
    })
}
async function GetPromiseAndWait(){
   let text=await GetMess()
   return '我处理完了'
}
async function WantGetFinallyText(){
    let data=await GetPromiseAndWait()
    console.log('WantGetFinallyText',data)
}

WantGetFinallyText()

图片.png

这个时候await就会阻塞住GetPromiseAndWait一直到履行状态再将其值赋值给data,因为return会使函数变为履行状态,也就是说await会使函数一直阻塞到return返回内容为止。

注意,还有一个知识点

就是GetPromiseAndWait如果return一个Promise,那这个函数返回的将是这个Promise,await阻塞的也是这个Promise的值。

这个概念我们之前也讲过,当async函数return一个值时,会将其包装成一个Promise,当返回一个Promise时,将直接返回这个Promise

那么到这里,你就学会了Promise以及多层Async函数的同步!

结语

撒花~

图片.png

2

主题

103

帖子

41

积分

新手上路

Rank: 1

积分
41

猫咪币纪念章活跃会员中秋纪念章

发表于 2021-8-23 07:43:34 | 显示全部楼层
赶上热乎的了 趁机占个楼
回复

使用道具 举报

8

主题

155

帖子

453

积分

中级会员

Rank: 3Rank: 3

积分
453

猫咪币纪念章活跃会员三好学生热心会员中秋纪念章

发表于 2021-8-23 08:10:05 | 显示全部楼层
太好了
布[
回复

使用道具 举报

131

主题

391

帖子

402

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
402

猫咪币纪念章三好学生活跃会员热心会员突出贡献中秋纪念章

发表于 2021-8-23 10:14:22 | 显示全部楼层
哥哥最近有点高产啊
Vx:rsnhkx2015  公众号:陈公子的话
回复

使用道具 举报

123

主题

932

帖子

550

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
550
发表于 2021-8-23 10:37:45 | 显示全部楼层
syy 发表于 2021-8-23 07:43
赶上热乎的了 趁机占个楼

谢谢哥哥
回复

使用道具 举报

123

主题

932

帖子

550

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
550
发表于 2021-8-23 10:37:50 | 显示全部楼层

谢谢哥哥
回复

使用道具 举报

123

主题

932

帖子

550

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
550
发表于 2021-8-23 10:38:02 | 显示全部楼层
小陈 发表于 2021-8-23 10:14
哥哥最近有点高产啊

闲着没事想先写几篇,哥哥要不要也写点玩玩
回复

使用道具 举报

发表回复

本版积分规则

快速回复 返回顶部 返回列表