ES6新特性八:async函數(shù)用法實例詳解
本文實例講述了ES6新特性之a(chǎn)sync函數(shù)用法。分享給大家供大家參考,具體如下:
1. async 函數(shù)是什么?
node.js 版本7及之后版本才支持該函數(shù)。
可以簡單的理解為他是Generator 函數(shù)的語法糖,即Generator 函數(shù)調(diào)用next()
返回的結(jié)果。
① Generator
函數(shù)需要next() 或執(zhí)行器進行執(zhí)行,而async 函數(shù)只需和普通函數(shù)一樣執(zhí)行。
② async
和await
,比起星號和yield
,語義更清楚了。async表示函數(shù)里有異步操作,await表示緊跟在后面的表達式需要等待結(jié)果,結(jié)果返回才會向下執(zhí)行。
③ async函數(shù)的返回值是 Promise 對象,這比 Generator 函數(shù)的返回值是 Iterator 對象方便多了。你可以用then方法指定下一步的操作。
2. async 函數(shù)與Generator 函數(shù)寫法對比
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()); }; var asyncReadFile = async function () { var f1 = await readFile('/etc/fstab'); var f2 = await readFile('/etc/shells'); console.log(f1.toString()); console.log(f2.toString()); };
3. async 函數(shù)的作用?
在異步程序中(比如在nodejs),在下一步程序中,需要異步返回的結(jié)果,由于是異步,下一步會在異步返回前就會執(zhí)行完,這時程序就會出現(xiàn)不是我們預想的結(jié)果。而async 函數(shù)就可以很好的解決這一問題。我們將異步操作放在await 后面,等待異步返回了結(jié)果程序才會向下執(zhí)行。
舉例:
/** * Created by Dason on 2017/3/12. */ var mysql = require('mysql'); var pool = mysql.createPool({ host : '127.0.0.1' , user : 'root' , password : 'root' , database : 'dason', multipleStatements: true }); //查詢所有id的方法 var getResult = function () { return new Promise(function(resolve,reject){ pool.getConnection(function(err,connection){ if(err){ console.log(err); throw err; } connection.query('SELECT id FROM user',function(err,result){ if(err){ //console.log(err); throw err; //reject(err); } console.log(result); //[{id:1},{id:2},{id:4},{id:5},{id:6},{id:3},{id:7}] connection.release(); resolve(result); }); }); }); }; //將所有人的name 改為 A var updateName = function(id) { pool.getConnection(function(err,connection){ if(err){ console.log(err); } connection.query("update user set name='A' where id = ?",[id],function(err,result){ if(err){ console.log(err); } connection.release(); }); }); }; async function update() { /** * getResult 是一個異步函數(shù),放在await 后面, * 當函數(shù)執(zhí)行的時候,一旦遇到await就會先返回, * 等到異步操作完成,將異步結(jié)果返回,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。 */ var result = await getResult(); console.log("result:"+JSON.stringify(result)); //result:[{"id":1},{"id":2},{"id":4},{"id":5},{"id":6},{"id":3},{"id":7}] for(const obj of result){ updateName(obj.id); } } update();// async函數(shù)調(diào)用和普通方法一樣
4. 語法
① async 函數(shù)返回一個promise
對象。
② async函數(shù)內(nèi)部return
語句返回的值,會成為then方法回調(diào)函數(shù)的參數(shù)。
③ async函數(shù)的await
命令后面,可以是Promise 對象和原始類型的值(數(shù)值、字符串和布爾值,但這時等同于同步操作),如果不是Promise 對象,會被轉(zhuǎn)成一個立即resolve的 Promise 對象。
async function f() { return 'hello world';//會自動調(diào)用Promise.resolve('hello world'),將其轉(zhuǎn)化為promise對象 } f().then(v => console.log(v)) // "hello world" async function f() { throw new Error('出錯了'); } f().then( v => console.log(v), e => console.log(e) ) // Error: 出錯了
④ async函數(shù)返回的 Promise 對象,必須等到內(nèi)部所有await命令后面的 Promise 對象執(zhí)行完,才會發(fā)生狀態(tài)改變,除非遇到return語句或者拋出錯誤。也就是說,只有async函數(shù)內(nèi)部的異步操作執(zhí)行完,才會執(zhí)行then方法指定的回調(diào)函數(shù)。
注意1:await命令后面的Promise對象,運行結(jié)果可能是rejected,所以最好把await命令放在try...catch代碼塊中。
async function main() { try { var val1 = await firstStep(); var val2 = await secondStep(val1); var val3 = await thirdStep(val1, val2); console.log('Final: ', val3); } catch (err) { console.error(err); } }
⑤ await命令后面的 Promise 對象如果變?yōu)?code>reject狀態(tài),則reject的參數(shù)會被catch
方法的回調(diào)函數(shù)接收到。
async function f() { await Promise.reject('出錯了');//沒有return,即不是async函數(shù)返回的promise對象,也會被catch方法的回調(diào)函數(shù)接收到 } f() .then(v => console.log(v)) .catch(e => console.log(e)) // 出錯了
注意2:多個await
命令后面的異步操作,如果不存在繼發(fā)關(guān)系,最好讓它們同時觸發(fā)。不然會增加耗時。
//耗時寫法 let foo = await getFoo(); let bar = await getBar(); //同時觸發(fā) // 寫法一 let [foo, bar] = await Promise.all([getFoo(), getBar()]); // 寫法二 let fooPromise = getFoo(); let barPromise = getBar(); let foo = await fooPromise; let bar = await barPromise;
希望本文所述對大家ECMAScript程序設(shè)計有所幫助。
- ES6中非常實用的新特性介紹
- JavaScript ES6的新特性使用新方法定義Class
- JavaScript中的Reflect對象詳解(ES6新特性)
- 深入淺出ES6新特性之函數(shù)默認參數(shù)和箭頭函數(shù)
- 簡單談?wù)凟S6的六個小特性
- ES6新特性之Symbol類型用法分析
- ES6(ECMAScript 6)新特性之模板字符串用法分析
- ES6新特性之變量和字符串用法示例
- ES6新特性之模塊Module用法詳解
- ES6新特性之字符串的擴展實例分析
- ES6新特性二:Iterator(遍歷器)和for-of循環(huán)詳解
- ES6新特性六:promise對象實例詳解
- ES6新特性七:數(shù)組的擴充詳解
- ES6新特性之類(Class)和繼承(Extends)相關(guān)概念與用法分析
- 讓微信小程序支持ES6中Promise特性的方法詳解
- ES6新特性:使用export和import實現(xiàn)模塊化詳解
- es6新特性之 class 基本用法解析
- ES6 13個新特性總結(jié)
相關(guān)文章
微信小程序?qū)崿F(xiàn)收藏與取消收藏切換圖片功能
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)收藏與取消收藏切換圖片功能,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-08-08Javascript中定義方法的另類寫法(批量定義js對象的方法)
用了很多的Javascript框架,偶爾也會去看一下框架的源碼,經(jīng)常會看到這樣的代碼。2011-02-02用js來定義瀏覽器中一個左右浮動元素相對于頁面主體寬度的位置的函數(shù)
用js來定義瀏覽器中一個左右浮動元素相對于頁面主體寬度的位置的函數(shù) 函數(shù)的參數(shù):elem元素、頁面主體寬度(如:990、950寬)、elem與頁面主體DIV的左邊距2012-01-01uniapp添加操作日志的方法(uniapp、日志、文件、html5+)
近期一直在寫微信小程序,有一個問題一直沒有解決,就是在測試環(huán)境中調(diào)試代碼會打印很多日志,方便看到問題所在,這篇文章主要給大家介紹了關(guān)于uniapp添加操作日志(uniapp、日志、文件、html5+)的相關(guān)資料,需要的朋友可以參考下2023-11-11JavaScript控制瀏覽器全屏及各種瀏覽器全屏模式的方法、屬性和事件
這篇文章主要介紹了JavaScript控制瀏覽器全屏及各種瀏覽器全屏模式的方法、屬性和事件的相關(guān)資料,需要的朋友可以參考下2015-12-12js動態(tài)創(chuàng)建上傳表單通過iframe模擬Ajax實現(xiàn)無刷新
這篇文章主要介紹了js動態(tài)創(chuàng)建上傳表單通過iframe模擬Ajax無刷新的具體實現(xiàn),需要的朋友可以參考下2014-02-02