当前位置: 首页 > 科技观察

用顶层await简化JS代码

时间:2023-03-20 22:35:25 科技观察

JavaScript是一种流行的编程语言,最初设计为单线程同步语言,意味着程序需要一步步执行,无需等待外部资源或耗时计算跑步。如果脚本需要此类资源或计算,则此同步行为将导致错误。这会阻止队列中的所有其他进程运行,无论它们是否依赖于那些被阻止的任务。但很久以前,JavaScript引入了一种机制,允许它在等待外部资源或耗时任务的同时执行其剩余代码。这种异步行为是通过对函数使用回调或承诺来实现的。什么是回调和承诺我将通过代码来解释这些概念。如果您已经知道回调和承诺是什么,请直接跳到顶级等待部分和示例应用程序。回调在回调中,一个函数作为参数传递给另一个函数;因此,下面的addEventListener函数中的第二个参数是回调函数。此回调将等待第一个点击事件发生,然后再执行第二个参数。constx=document.getElementsByTagName('Button');x[0].addEventListener('click',()=>{alert("Iwasclicked")})这种等待行为使得代码异步。这与同步代码不同,同步代码可以一步步运行,无需等待资源下载或耗时进程结束。但请注意,并非所有回调函数都是异步的。PromisesPromises类似于回调,它将函数附加到返回的对象。但是Promises和回调也不同,Promises是专门为异步方法设计的。它们只有一个参数和一个then()函数来取回结果。此外,它可以链接多个.then()和catch()函数。fetch('www.xyz.com/api').then((res)=>{letx=res.data;//dosomethingwithreceiveddata}).catch((err)=>{console.log(err)})承诺使用事件队列并严格遵循异步任务链接的顺序。Async/awaitAsync/await是对Promises的语法改进,以避免链式调用。它使代码更清晰,更容易理解。await关键字导致代码暂停,直到Promises成功(解决)或失败(解决)。asyncfunctionasyncwaitcode(){letgetData=awaitaxios('www.xyzdata.org/api')console.log(getData.data)}顶层的await是什么上面所有的例子都让functionblock中的代码异步,没有一个在模块级别工作。但是,异步行为可以在模块级别实现。使用顶级await的模块将在通知该模块的使用者继续执行其自己的代码之前异步初始化其命名空间。下面的示例代码显示了如何使用顶级等待。关于应用程序此应用程序将从新闻API中获取最流行的新闻数据,并将其呈现在浏览器中。用户还可以使用相关搜索词搜索新闻数据。在我们开始之前,有几点需要注意:node13.3及更高版本支持顶级await。顶级await仅在ECMAScript模块中受支持,但Node.js和Express都是CmmonJS模块。CmmonJS不支持顶级等待功能。所以我会在代码中使用import而不是require在node14.x之前,top-levelawait不能直接使用,需要开启--harmony循环引用模块可能会导致死锁BuildApp1.创建toplevelawait目录$mkdirtoplevelawait2.npminit初始化$npminit3.在package.json中添加"type":"module"以支持ECMAScript模块"author":"","license":"ISC","type":"module",4.在toplevelaitdirectory下创建src目录。请注意使用mjs作为文件扩展名。$touchapp.mjs$touchexp.mjs$ls-1srcapp.mjsexp.mjs5.安装依赖axios,ejs和express$npmintallaxiosejsexpress--save6.在exp.mjs中添加如下代码:importexpressfrom"express"exportconstexp=awaitexpress();请注意,我们正在使用没有异步的等待。这样,express实例会先被初始化,然后导出到其他模块。在执行依赖于该模块的代码之前,您可以使用它来等待模块中的实例被初始化。如果模块包含顶级await,则其父模块的执行将停止,直到实现承诺。但是他的兄弟模块会继续执行,和之前的同步方式一样。请注意,Node.js中的模块加载也是同步的,这意味着它不能异步等待资源加载。但是可以在加载或处理资源的语句前加上await关键字,实现异步等待。添加新闻API此应用程序使用两个免费的新闻API来获取数据。两个API都支持后备依赖行为;如果一个API失败,另一个API将获取数据。两个API都使用API密钥:NewsAPI[1]GNewsAPI[2]在app.mjs文件中插入以下代码。之前的目标导入了axios和在exp.js中初始化的express实例。下一节设置视图引擎以在浏览器中显示。import{exp}from"./exp.mjs";importaxiosfrom"axios"exp.set("viewengine","ejs");//dependencyfallbackletresponse="";letsite=true;try{response=awaitaxios('https://newsapi.org/v2/top-headlines?country=us&apiKey=your-api-key');}catch{response=awaitaxios("https://gnews.io/api/v3/top-news?token=your-api-key");site=false;}//Gettopnewsexp.get('/',function(req,res){letresponseresponse0=response.data.articlesres.render('main.ejs',{response0:response0,site:site})})//searchnewsexp.get('/search',function(req,res){res.render("searchnews.ejs")})exp.get('/result',async(req,res)=>{letx=req.query.newtitlesearch;letresponse1={}letdata={}try{leturl='https://newsapi.org/v2/everything?q='+x+'&apiKey=your-api-key'response1=awaitaxios(url);}catch{leturl='https://gnews.io/api/v3/search?q='+x+'&token=your-api-key'response1=awaitaxios(url)}res.render('result.ejs',{response1:response1.data.articles,site:site})})exp.listen(3000)最重要的部分是这个trycatch块,它使用顶层的await等待axios获取数据。如果由于任何原因,axios无法从第一个API获取数据,应用程序将使用第二个API获取数据。一旦它从API获取数据,express就可以在主页上呈现它。try{response=awaitaxios('https://newsapi.org/v2/top-headlines?country=us&apiKey=your-api-key');}catch{response=awaitaxios("https://gnews.io/api/v3/top-news?token=your-api-key");}接下来提供一个让用户可以搜索的路由://searchnewsexp.get('/search',function(req,res){res.render("../src/view/sea??rchnews.ejs")})最后,显示搜索结果的另一个路径:exp.get('/result',async(req,res)=>{letx=req.query。newtitlesearch;letresponse1={}letdata={}try{leturl='https://newsapi.org/v2/everything?q='+x+'&apiKey=your-api-key'response1=awaitaxios(url);}抓住{leturl='https://gnews.io/api/v3/search?q='+x+'&token=your-api-key'response1=awaitaxios(url)}res.render('../src/view/result.ejs',{response1:response1.data.articles,site:site})})编写前端界面应用的最后一部分是为前端页面编写四个.ejsHTML文件。将这些文件保存在“view”文件夹中://header.ejsnewapiappNewsapp

  • 主要
  • 搜索
  • >/nav>//main.ejs<%include('header');%><%letrows=response0%><%letsitesiterep=site%><%for(leti=0;i">">
    <%=rows[i].title%>
    <%}%>//searchnews.ejs<%-include('header');%>

    Searchnews

    //result.ejs<%-include('header');%><%letrows=response1%><%letsitesiterep=site%><%for(leti=0;i">">div><%=rows[i].title%><%}%>运行APP现在APP已经完成了,大家可以试试看正在使用node.jsv13.3到v14.0,运行:$node--harmony-top-level-awaitapp.js如果您使用的是node.jsv14.0及更高版本,则不需要--harmony标志:$nodeapp.js如果你已经成功构建了这个应用程序,恭喜你,你学到了一个新的js特性。你可以在ECMAScriptTC39top-levelawaitproposal[3]中获得更多信息。