自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用頂層await簡(jiǎn)化JS代碼

開發(fā) 前端
JavaScript 引入了一個(gè)機(jī)制讓其可以在等待外部資源或者耗時(shí)任務(wù)的時(shí)候去執(zhí)行其剩余的代碼。這種異步行為是通過(guò)在函數(shù)上使用回調(diào)或 promise 來(lái)實(shí)現(xiàn)的。

[[386526]]

 JavaScript 是一種流行的編程語(yǔ)言,最初被設(shè)計(jì)為單線程和同步的語(yǔ)言,意味著程序需要在不等待獲取外部資源或者耗時(shí)的計(jì)算的情況下一步一步的運(yùn)行。如果腳本需要這樣的資源或計(jì)算,這種同步行為將導(dǎo)致錯(cuò)誤。這會(huì)阻塞隊(duì)列中的所有其他進(jìn)程運(yùn)行,無(wú)論它們是否依賴于那些阻塞中的任務(wù)。

但很久以前,JavaScript 引入了一個(gè)機(jī)制讓其可以在等待外部資源或者耗時(shí)任務(wù)的時(shí)候去執(zhí)行其剩余的代碼。這種異步行為是通過(guò)在函數(shù)上使用回調(diào)或 promise 來(lái)實(shí)現(xiàn)的。

什么是回調(diào)和promise

我將通過(guò)代碼來(lái)解釋這些概念。如果你已經(jīng)知道回調(diào)和 promise 是什么,請(qǐng)直接跳到頂層 await 部分和示例應(yīng)用程序。

回調(diào)

在回調(diào)中,一個(gè)函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù);因此,下面 addEventListener 函數(shù)中的第二個(gè)參數(shù)是回調(diào)函數(shù)。此回調(diào)將等待第一個(gè) click 事件發(fā)生,然后才執(zhí)行第二個(gè)參數(shù)。 

  1. const x = document.getElementsByTagName('Button');  
  2. x[0].addEventListener('click',() =>{alert("I was clicked")}) 

這種等待行為使代碼異步。這與同步代碼不同,它可以接著一步一步的運(yùn)行,而不需要等待資源下載或者耗時(shí)進(jìn)程結(jié)束。但要注意,并非所有回調(diào)函數(shù)都是異步的。

Promises

Promises 類似于回調(diào),它將函數(shù)附加到返回的對(duì)象上。但Promises和回調(diào)也有不同,Promises 是專門為異步方法設(shè)計(jì)的。它們只有一個(gè)參數(shù)和一個(gè)用來(lái)獲得返回結(jié)果的 then() 函數(shù)。此外,它還可以鏈?zhǔn)降母郊佣鄠€(gè).then() 和 catch() 函數(shù)。 

  1. fetch('www.xyz.com/api')  
  2. .then((res)=>{let x = res.data; //do something with received data})  
  3. .catch((err)=>{console.log(err)}) 

Promises使用事件隊(duì)列并嚴(yán)格遵循異步任務(wù)被鏈接的順序來(lái)執(zhí)行。

Async/await

Async/await 是對(duì) Promises 的語(yǔ)法改進(jìn),以避免鏈?zhǔn)秸{(diào)用。它能使代碼更清晰,更容易理解。await 關(guān)鍵字使代碼暫停,直到 Promises 成功(resolved)或者失?。╮esolved)。 

  1. async function asyncwaitcode(){  
  2.   let getData = await axios('www.xyzdata.org/api')  
  3.   console.log(getData.data)  

什么是頂層 await

以上所有示例都讓功能塊中的代碼異步,沒(méi)有一個(gè)在模塊級(jí)工作。

但是,異步行為是可以在模塊級(jí)別實(shí)現(xiàn)的。使用頂級(jí) await 的模塊會(huì)在異步初始化其命名空間后,再通知該模塊的消費(fèi)者繼續(xù)執(zhí)行它自己的代碼。

下面的示例代碼展示了如何使用頂級(jí) await。

關(guān)于App

此應(yīng)用將從新聞 API 中獲取最熱門的新聞數(shù)據(jù),并在瀏覽器中呈現(xiàn)。用戶還能以相關(guān)搜索詞的進(jìn)行新聞數(shù)據(jù)搜索。在開始之前,有幾點(diǎn)需要注意:

  •  頂級(jí)await在node 13.3及更高版中被支持
  •  頂級(jí)await只在ECMAScript模塊中支持,但Node.js和Express都是CmmonJS模塊。CmmonJS不支持頂級(jí)await特性。所以我在代碼中會(huì)使用import而不是require
  •  在node 14.x之前,頂級(jí)await不能直接使用,需要啟用--harmony
  •  循環(huán)引用模塊可能會(huì)導(dǎo)致死鎖

構(gòu)建App

    1.  創(chuàng)建toplevelawait目錄

  1. $ mkdir toplevelawait 

    2.  npm init初始化

  1. $ npm init 

    3.package.json中增加"type": "module",以支持ECMAScript模塊 

  1. "author": "",  
  2. "license": "ISC",  
  3. "type": "module", 

   4.在toplevelawait目錄下創(chuàng)建src目錄。注意使用mjs作為文件后綴名。 

  1. $ touch app.mjs  
  2. $ touch exp.mjs  
  3. $ ls -1 src  
  4. app.mjs 
  5. exp.mjs 

    5.  安裝依賴axios, ejs和 express 

  1. $ npm install axios ejs express --save 

    6.  exp.mjs中增加下面代碼: 

  1. import express from "express"  
  2. export const exp = await express(); 

注意我們是在沒(méi)有async的情況下使用await。這樣express實(shí)例會(huì)先初始化后再導(dǎo)出給其他模塊。你可以用這種方式等待模塊中某個(gè)實(shí)例初始化后完成后,再執(zhí)行依賴于該模塊的代碼。

如果一個(gè)模塊包含了頂層await,那么它的父模塊的執(zhí)行會(huì)停止,直到promise完成。但他的兄弟模塊會(huì)繼續(xù)執(zhí)行,和以前的同步模式相同。

要注意Node.js中的模塊加載也是同步的,意味著他不能異步的等待資源加載。但你可以在加載或者處理資源的語(yǔ)句前加上await關(guān)鍵字來(lái)實(shí)現(xiàn)異步等待。

增加news APIs

這個(gè)應(yīng)用使用兩個(gè)免費(fèi)的新聞API來(lái)獲取數(shù)據(jù)。兩個(gè)API支持回退依賴行為;如果一個(gè)API失敗,另一個(gè)API將獲取數(shù)據(jù)。這兩個(gè)API都使用API密鑰:

  •  News API[1]
  •  GNews API[2]

在app.mjs文件中插入下面的代碼。前面的目標(biāo)導(dǎo)入axios和在exp.js被初始化的express實(shí)例。下一部分設(shè)置視圖引擎,以便在瀏覽器中展示。 

  1. import { exp } from "./exp.mjs";  
  2. import axios from "axios"  
  3. exp.set("view engine","ejs");  
  4. // dependency fall back  
  5. let response = "" 
  6. let site = true 
  7. try{  
  8.    response = await axios('https://newsapi.org/v2/top-headlines?country=us&apiKey=your-api-key');    
  9.  }  
  10.  catch{  
  11.   response = await axios("https://gnews.io/api/v3/top-news?token=your-api-key");  
  12.   site = false 
  13.  }  
  14.  // Get top news  
  15. exp.get('/',function(req,res){  
  16.   let responseresponse0 = response.data.articles    
  17.   res.render('main.ejs',{response0: response0, site:site})  
  18.  })  
  19.  // search news  
  20. exp.get('/search', function(req,res){  
  21.   res.render("searchnews.ejs")    
  22. })  
  23. exp.get('/result', async(req, res)=> 
  24.   let x = req.query.newtitlesearch;  
  25.   let response1 = {}  
  26.   let data = {}  
  27.   try{  
  28.     let url = 'https://newsapi.org/v2/everything?q='+x+'&apiKey=your-api-key'  
  29.     response1 =  await axios(url); 
  30.   }  
  31.   catch{  
  32.     let url = 'https://gnews.io/api/v3/search?q='+x+'&token=your-api-key'  
  33.     response1 =  await axios(url) 
  34.    }  
  35.   res.render('result.ejs', {response1: response1.data.articles, site: site})    
  36. })  
  37. exp.listen(3000) 

最重要的部分是這個(gè)try catch塊,使用到了頂層await來(lái)等待axios去獲取數(shù)據(jù)。如果由于任何原因,axios無(wú)法從第一個(gè)API獲取數(shù)據(jù),應(yīng)用將使用第二個(gè)API獲取數(shù)據(jù)。一旦它從API獲得數(shù)據(jù),express可以在主頁(yè)上呈現(xiàn)它。 

  1. try{  
  2.    response = await axios('https://newsapi.org/v2/top-headlines?country=us&apiKey=your-api-key');   
  3.  }  
  4.  catch{  
  5.   response = await axios("https://gnews.io/api/v3/top-news?token=your-api-key");   
  6.  } 

接下來(lái)提供了一個(gè)可以讓用戶進(jìn)行搜索的路由: 

  1. // search news  
  2. exp.get('/search', function(req,res){  
  3.   res.render("../src/view/searchnews.ejs")  }) 

最后,另一個(gè)路徑展示搜索結(jié)果: 

  1. exp.get('/result', async(req,res)=> 
  2.   let x = req.query.newtitlesearch;  
  3.   let response1 = {}  
  4.   let data = {}  
  5.   try{  
  6.     let url = 'https://newsapi.org/v2/everything?q='+x+'&apiKey=your-api-key' 
  7.     response1 =  await axios(url);  
  8.   }  
  9.   catch{  
  10.     let url = 'https://gnews.io/api/v3/search?q='+x+'&token=your-api-key'  
  11.     response1 =  await axios(url)  
  12.   }  
  13.   res.render('../src/view/result.ejs', {response1: response1.data.articles , site: site})    
  14. }) 

寫前端界面

應(yīng)用的最后一部分是為前端頁(yè)面編寫四個(gè).ejs HTML文件。將這些文件保存在“view”文件夾中: 

  1. //header.ejs  
  2. <!DOCTYPE html>  
  3. <head>  
  4.     <title>newapiapp</title>  
  5.     <link type="text/css" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" ></head><body>    
  6.     <nav class="navbar navbar-default">  
  7.               <div class="container-fluid">  
  8.                   <div class="navbar-header">  
  9.                       <a class="navbar-brand" href="#">News app</a>  
  10.                   </div>  
  11.                   <div class="collapse navbar-collapse">  
  12.                       <ul class="nav navbar-nav navbar-right">  
  13.                              <li><a href="/">Main</a></li>             
  14.                                <li><a href="/search">Search</a></li>    
  15.                        </ul>      
  16.                    </div> 
  17.                </div>   
  18.      </nav>  
  1. //main.ejs  
  2. <%include('header');%>  
  3. <%let rows = response0%>  
  4. <%let sitesiterep = site%>  
  5. <div name "container">  
  6.   <div class="row text-center" style="display:flex; flex-wrap:wrap">  
  7.     <% for(let i = 0; i < rows.length; i++){%>  
  8.       <div class="col-md-3 col-sm-6 ">  
  9.                           <div class="thumbnail" >  
  10.                             <a href="<%-rows[i].url %>">  
  11.                               <img src = "<%= siterep ? rows[i].urlToImage :  rows[i].url  %>">  
  12.                             </a>                              
  13.                           </div>  
  14.                           <div><%= rows[i].title%></div>              
  15.                          </div>      
  16.     <% } %>  
  17.   </div>    
  18. </div>  
  1. //searchnews.ejs  
  2. <%- include('header');%>  
  3.   <h1>Search news </h1>  
  4.   <form action="/result" method="Get">  
  5.       <input type ="text" placeholder="news title search" name="newtitlesearch"></input>  
  6.         <input type="submit" placeholder="submit"></input>          
  7.    </form>  
  1. //result.ejs  
  2. <%- include('header');%>  
  3. <%let rows = response1%>  
  4. <%let sitesiterep = site%>  
  5. <div name "container">  
  6.   <div class="row text-center" style="display:flex; flex-wrap:wrap">  
  7.     <% for(let i = 0; i < rows.length; i++){%>  
  8.       <div class="col-md-3 col-sm-6 ">  
  9.                           <div class="thumbnail" >  
  10.                             <a href="<%-rows[i].url %>">  
  11.                               <img src = "<%= siterep ? rows[i].urlToImage :  rows[i].url  %>">  
  12.                             </a>                          
  13.                            </div>  
  14.                           <div><%= rows[i].title%></div>                  
  15.                          </div>    
  16.      <% } %>  
  17.   </div>   
  18.  </div> 

運(yùn)行app

現(xiàn)在APP已經(jīng)完成,你可以嘗試下。

如果你在使用node.js v13.3 至 v14.0,運(yùn)行: 

  1. $ node --harmony-top-level-await app.js 

如果你在使用node.js v14.0以上,你不需要--harmony flag: 

  1. $ node app.js 

如果你成功構(gòu)建了這個(gè)app,那么恭喜你又學(xué)會(huì)了一個(gè)新的js特性。

你可以在 ECMAScript TC39 top-level await提案[3] 中獲得更多的信息。 

 

責(zé)任編輯:龐桂玉 來(lái)源: 前端大全
相關(guān)推薦

2024-12-05 14:06:29

JS代碼片段

2025-04-03 04:11:00

JS代碼URL

2021-11-17 16:24:23

JS 代碼函數(shù)聲明

2024-05-28 00:03:00

JavaScript開發(fā)

2023-04-14 08:10:59

asyncawait

2009-07-22 07:47:00

Scala客戶代碼

2017-04-19 08:47:42

AsyncJavascript異步代碼

2012-07-22 15:59:42

Silverlight

2011-01-24 13:20:49

2022-11-21 09:01:00

Swift并發(fā)結(jié)構(gòu)

2017-11-16 16:15:28

Await開發(fā)嵌套

2009-07-06 15:20:30

JSP表達(dá)式

2023-04-02 14:09:51

2019-11-27 10:05:00

LombokJava編程

2009-06-22 14:26:12

ScalaXML對(duì)象

2021-11-12 05:00:43

裝飾器代碼功能

2017-04-05 15:45:20

2013-05-17 09:41:02

Node.js云應(yīng)用開發(fā)IaaS

2022-06-16 10:37:09

asyncawait

2022-06-24 08:33:13

ECMAScriptjavaScript
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)