目錄
三、async 函數的優點" >三、async 函數的優點
四、async 函數的實作" >四、async 函數的實作
五、async 函數的用法" >五、async 函數的用法
六、注意點" >六、注意點
首頁 web前端 js教程 js中async函數使用方法詳解

js中async函數使用方法詳解

May 22, 2018 am 09:44 AM
async javascript 使用方法

這次帶給大家js中async函數使用方法詳解,js中async函數使用的注意事項有哪些,下面就是實戰案例,一起來看一下。

一、終極解決

非同步操作是JavaScript 程式設計的麻煩事,麻煩到一直有人提出各種各樣的方案,試圖解決這個問題。

從最早的回呼函數,到 Promise 對象,再到 Generator 函數,每次都有所改進,但又讓人覺得不徹底。它們都有額外的複雜性,都需要理解抽象的底層運作機制。

非同步I/O不就是讀取一個檔案嗎,幹嘛要搞得這麼複雜?非同步程式設計的最高境界,就是根本不用在意它是不是非同步。

async 函數就是隧道盡頭的亮光,很多人認為它是非同步操作的終極解決方案。

二、async 函數是什麼?

一句話,async 函數就是 Generator 函數的語法糖。

前文有一個 Generator 函數,依序讀取兩個檔案。

var fs = require('fs');
var readFile = function (fileName){
 return new Promise(function (resolve, reject){
  fs.readFile(fileName, function(error, data){
   if (error) reject(error);
   resolve(data);
  });
 });
};
var gen = function* (){
 var f1 = yield readFile('/etc/fstab');
 var f2 = yield readFile('/etc/shells');
 console.log(f1.toString());
 console.log(f2.toString());
};
登入後複製

寫成 async 函數,就是下面這樣。

var asyncReadFile = async function (){
 var f1 = await readFile('/etc/fstab');
 var f2 = await readFile('/etc/shells');
 console.log(f1.toString());
 console.log(f2.toString());
};
登入後複製

一比較就會發現,async 函數就是將 Generator 函數的星號(*)替換成 async,將 yield 替換成 await,僅此而已。

三、async 函數的優點

async 函數對 Generator 函數的改進,體現在以下三點。

(1)內建執行器。 Generator 函數的執行必須靠執行器,所以才有了 co 函式庫,而 async 函式自帶執行器。也就是說,async 函數的執行,與一般函數一模一樣,只要一行。

var result = asyncReadFile();

(2)更好的語意。 async 和 await,比起星號和 yield,語意更清楚了。 async 表示函數裡有非同步操作,await 表示緊接在後面的表達式需要等待結果。

(3)更廣的適用性。 co 函數庫約定,yield 指令後面只能是Thunk 函數或Promise 對象,而async 函數的await 指令後面,可以跟Promise 物件和原始型別的值(數值、字串和布林值,但這時等同於同步操作)。

四、async 函數的實作

async 函數的實現,就是將 Generator 函數和自動執行器,包裝在一個函數裡。

async function fn(args){
 // ...
}
// 等同于
function fn(args){ 
 return spawn(function*() {
  // ...
 }); 
}
登入後複製

所有的 async 函數都可以寫成上面的第二種形式,其中的 spawn 函數就是自動執行器。

以下給出 spawn 函數的實現,基本上就是前文自動執行器的翻版。

function spawn(genF) {
 return new Promise(function(resolve, reject) {
  var gen = genF();
  function step(nextF) {
   try {
    var next = nextF();
   } catch(e) {
    return reject(e); 
   }
   if(next.done) {
    return resolve(next.value);
   } 
   Promise.resolve(next.value).then(function(v) {
    step(function() { return gen.next(v); });   
   }, function(e) {
    step(function() { return gen.throw(e); });
   });
  }
  step(function() { return gen.next(undefined); });
 });
}
登入後複製

async 函數是非常新的語法功能,新到都不屬於 ES6,而是屬於 ES7。目前,它仍處於提案階段,但是轉碼器 Babel 和 regenerator 都已經支持,轉碼後就能使用。

五、async 函數的用法

#同 Generator 函數一樣,async 函數傳回一個 Promise 對象,可以使用 then 方法加入回調函數。當函數執行的時候,一旦遇到 await 就會先回,等到觸發的非同步操作完成,再接著執行函數體內後面的語句。

下面是一個例子。

async function getStockPriceByName(name) {
 var symbol = await getStockSymbol(name);
 var stockPrice = await getStockPrice(symbol);
 return stockPrice;
}
getStockPriceByName('goog').then(function (result){
 console.log(result);
});
登入後複製

上面程式碼是一個取得股票報價的函數,函數前面的async關鍵字,表示該函數內部有非同步操作。呼叫函數時,會立即傳回一個Promise物件。

下面的例子,指定多少毫秒後輸出一個值。

function timeout(ms) {
 return new Promise((resolve) => {
  setTimeout(resolve, ms);
 });
}
async function asyncPrint(value, ms) {
 await timeout(ms);
 console.log(value)
}
asyncPrint('hello world', 50);
登入後複製

上面程式碼指定50毫秒以後,輸出"hello world"。

六、注意點

await 指令後面的Promise 對象,運行結果可能是rejected,所以最好把await 指令放在try ...catch 程式碼區塊中。

async function myFunction() {
 try {
  await somethingThatReturnsAPromise();
 } catch (err) {
  console.log(err);
 }
}
// 另一种写法
async function myFunction() {
 await somethingThatReturnsAPromise().catch(function (err){
  console.log(err);
 });
}
登入後複製

await 指令只能用在 async 函數之中,如果用在普通函數,就會報錯。

async function dbFuc(db) {
 let docs = [{}, {}, {}];
 // 报错
 docs.forEach(function (doc) {
  await db.post(doc);
 });
}
登入後複製

上面代码会报错,因为 await 用在普通函数之中了。但是,如果将 forEach 方法的参数改成 async 函数,也有问题。

async function dbFuc(db) {
 let docs = [{}, {}, {}];
 // 可能得到错误结果
 docs.forEach(async function (doc) {
  await db.post(doc);
 });
}
登入後複製

上面代码可能不会正常工作,原因是这时三个 db.post 操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用 for 循环。

async function dbFuc(db) {
 let docs = [{}, {}, {}];
 for (let doc of docs) {
  await db.post(doc);
 }
}
登入後複製

如果确实希望多个请求并发执行,可以使用 Promise.all 方法。

async function dbFuc(db) {
 let docs = [{}, {}, {}];
 let promises = docs.map((doc) => db.post(doc));
 let results = await Promise.all(promises);
 console.log(results);
}
// 或者使用下面的写法
async function dbFuc(db) {
 let docs = [{}, {}, {}];
 let promises = docs.map((doc) => db.post(doc));
 let results = [];
 for (let promise of promises) {
  results.push(await promise);
 }
 console.log(results);
}
登入後複製

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Nodejs内存治理步骤详解

Vue页面骨架屏注入步骤详解

以上是js中async函數使用方法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1658
14
CakePHP 教程
1415
52
Laravel 教程
1309
25
PHP教程
1257
29
C# 教程
1231
24
DirectX修復工具怎麼用? DirectX修復工具詳細使用方法 DirectX修復工具怎麼用? DirectX修復工具詳細使用方法 Mar 15, 2024 am 08:31 AM

  DirectX修復工具是專業的系統工具,主要功能是偵測目前系統的DirectX狀態,如果發現異常就可以直接修復。可能還有很多用戶不清楚DirectX修復工具怎麼用吧,以下就來看看詳細教學。  1、使用修復工具軟體進行修復檢測。  2、如果修復完成後提示C++元件有異常的問題,請點選取消按鈕,然後點選工具選單列。  3、點選選項按鈕,選擇擴展,點選開始擴展按鈕。  4、擴展完成後再重新進行檢測修復即可。  5、如果修復工具操作完成後仍未解決問題,可以嘗試卸載重新安裝報錯的程序。

HTTP 525狀態碼介紹:探究其定義與應用 HTTP 525狀態碼介紹:探究其定義與應用 Feb 18, 2024 pm 10:12 PM

HTTP525狀態碼簡介:了解其定義與使用方法HTTP(HypertextTransferProtocol)525狀態碼是指伺服器在SSL握手過程中發生錯誤,導致無法建立安全連線。在傳輸層安全性(TLS)握手期間發生錯誤時,伺服器將傳回此狀態碼。此狀態碼屬於伺服器錯誤類別,通常表示伺服器配置或設定問題。當客戶端嘗試透過HTTPS連接到伺服器時,伺服器無

百度網盤怎麼用-百度網盤的使用方法 百度網盤怎麼用-百度網盤的使用方法 Mar 04, 2024 pm 09:28 PM

有很多朋友還不知道百度網盤怎麼用,所以下面小編就講解了百度網盤的使用方法,有需要的小伙伴趕緊來看一下吧,相信對大家一定會有所幫助哦。第一步:安裝好百度網盤後直接登入(如圖);第二步:接著可依頁面提示選擇「我的分享」與「傳輸清單」(如圖);第三步:在「好友分享」裡可以把圖片和檔案直接分享給好友(如圖所示);第四步:接著選擇「分享」後可勾選電腦檔案或是網盤檔案(如圖所示);第五步:然後就可以尋找好友(如圖所示);第六步:還可以在「功能寶箱」中尋找自己需要的功能(如圖所示)。上面就是小編為大

KMS啟動工具是什麼? KMS啟動工具怎麼用? KMS啟動工具使用方法? KMS啟動工具是什麼? KMS啟動工具怎麼用? KMS啟動工具使用方法? Mar 18, 2024 am 11:07 AM

KMS啟動工具是一種用來啟動微軟Windows和Office產品的軟體工具。 KMS是KeyManagementService的縮寫,即金鑰管理服務。 KMS啟動工具透過模擬KMS伺服器的功能,使得電腦可以連接到這個虛擬的KMS伺服器,從而實現對Windows和Office產品的啟動。 KMS激活工具體積小巧,功能強大,可以一鍵永久激活,無需聯網狀態就可以激活任何版本的window系統和任何版本的Office軟體,是目前最成功的且經常更新的Windows激活工具,今天小編就跟大家介紹一下kms激活工

快速學會複製和貼上操作 快速學會複製和貼上操作 Feb 18, 2024 pm 03:25 PM

複製貼上快捷鍵使用方法複製貼上是我們在日常使用電腦時經常會遇到的操作。為了提高工作效率,熟練複製貼上快捷鍵是非常重要的。本文將介紹一些常用的複製貼上快捷鍵使用方法,幫助讀者更方便地進行複製貼上操作。複製快速鍵:Ctrl+CCtrl+C是複製的快速鍵,按住Ctrl鍵然後再按C鍵,即可將選取的文字、檔案、圖片等內容複製到剪貼簿。要使用該快捷鍵,

如何使用快捷鍵合併儲存格 如何使用快捷鍵合併儲存格 Feb 26, 2024 am 10:27 AM

合併儲存格的快速鍵怎麼用在日常工作中,我們常常需要對表格進行編輯和排版。而合併單元格是一種常見的操作,可以將相鄰的多個單元格合併為一個單元格,以提高表格的美觀程度和資訊展示效果。在MicrosoftExcel和GoogleSheets等主流的電子表格軟體中,合併儲存格的操作非常簡便,可以透過快速鍵來實現。以下將介紹在這兩個軟體中合併儲存格的快速鍵用法。在

potplayer怎麼用-potplayer的使用方法 potplayer怎麼用-potplayer的使用方法 Mar 04, 2024 pm 06:10 PM

potplayer是一款非常強大的媒體播放器,但不少夥伴還不知道potplayer怎麼用,今天小編就來詳細介紹一下potplayer的使用方法,希望能幫助大家。 1.PotPlayer快捷鍵PotPlayer播放器預設常用快捷鍵如下:(1)播放/暫停:空格(2)音量:滑鼠滾輪,上下方向鍵(3)前進/後退:左右方向鍵(4)書籤:P-加入書籤,H-查看書籤(5)全螢幕/還原:Enter(6)倍速:C-加速,X-減速,Z-復位(按一次調整0.1倍速度,可以在0.2到12倍速之間調節)( 7)上/下一幀:D/

PyCharm是什麼?功能介紹與使用方法詳解 PyCharm是什麼?功能介紹與使用方法詳解 Feb 20, 2024 am 09:21 AM

PyCharm是一款由JetBrains公司開發的專業的Python整合開發環境(IDE),它為Python開發者提供了強大的功能和工具,使得編寫Python程式碼更有效率、更方便。 PyCharm支援多種作業系統,包括Windows、macOS和Linux,同時也支援多種Python版本,並且提供了豐富的插件和擴充功能,方便開發者根據自己的需求客製化IDE環境。 P

See all articles