溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

ES6新特性八:async函數(shù)用法實例詳解

發(fā)布時間:2020-09-01 02:21:52 來源:腳本之家 閱讀:188 作者:Dason_yu 欄目:web開發(fā)

本文實例講述了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í)行。

asyncawait,比起星號和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)不是我們預(yù)想的結(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 后面,
  * 當(dāng)函數(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ù)。

注意1await命令后面的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è)計有所幫助。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI