ES6 async函数详解:语法、用法与Generator对比

作者:拾光

时间:2026-10-22

浏览:279

本文详解ES6中async函数的用法,阐述其作为Generator函数语法糖的特性。通过对比两者写法,解析async/await语法、Promise返回值及错误处理机制,并提供Node.js环境下的实际代码示例,帮助开发者掌握异步编程的最佳实践。

文章目录

本文详细介绍ES6新增的async函数用法,并提供具体示例供参考。

async 函数定义与特性

1. async 函数是什么?

该函数仅在Node.js版本7及以上版本中受支持。

可以将其简单理解为Generator函数的语法糖,即Generator函数调用next()返回的结果。

① Generator函数需要调用next()或执行器来驱动执行,而async函数则像普通函数一样直接执行即可。

② async和await相比星号和yield,语义表达更为清晰。async关键字表明函数内部包含异步操作,await关键字表示其后的表达式必须等待结果返回后,代码才会继续向下执行。

③ async函数的返回值是一个Promise对象,这比Generator函数返回的Iterator对象更为便捷,用户可以直接使用then方法来指定后续操作。

2. async 函数与Generator 函数写法对比

async 函数与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());
};
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 函数的作用

3. async 函数的作用?

在Node.js等异步编程场景中,若后续步骤依赖异步操作返回的结果,由于异步特性,后续代码可能在结果返回前就已执行完毕,导致程序行为与预期不符。async函数能有效解决此问题:将异步操作置于await之后,程序会等待异步结果返回后再继续向下执行。

举例:


/**
 * 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 是一个异步函数,放在await 后面,
  * 当函数执行的时候,一旦遇到await就会先返回,
  * 等到异步操作完成,将异步结果返回,再接着执行函数体内后面的语句。
  */
 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函数调用和普通方法一样

async 函数语法详解

4. 语法

① async函数返回一个promise对象。

② async函数内部return语句返回的值,将作为then方法回调函数的参数。

③ await命令后面可以跟随Promise对象或原始类型的值(数值、字符串和布尔值,此时等同于同步操作)。若不是Promise对象,系统会自动将其封装为一个立即resolve的Promise对象。


async function f() {
 return 'hello world';//会自动调用Promise.resolve('hello world'),将其转化为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函数返回的Promise对象,其状态改变需等待内部所有await命令后的Promise对象执行完毕才会发生,除非遇到return语句或抛出错误。换言之,只有async函数内部的异步操作全部执行完毕,then方法指定的回调函数才会执行。

注意1:await命令后的Promise对象运行结果可能是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对象变为reject状态,则reject的参数会被catch方法的回调函数接收。


async function f() {
 await Promise.reject('出错了');//没有return,即不是async函数返回的promise对象,也会被catch方法的回调函数接收到
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了

注意2:若多个await命令后的异步操作不存在继发关系,建议让它们同时触发,以避免不必要的耗时增加。


//耗时写法
let foo = await getFoo();
let bar = await getBar();
//同时触发
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;

希望本文所述内容对大家掌握ECMAScript程序设计有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章