ES6(八) async函数

1. async 函数是什么?

node.js 版本7及之后版本才支持该函数。
可以简单的理解为他是Generator 函数的语法糖,即Generator 函数调用next() 返回的结果。
① Generator 函数需要next() 或执行器进行执行,而async 函数只需和普通函数一样执行。
② async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果,结果返回才会向下执行
③ async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
④ async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

2. 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());
};

3. async 函数的作用?

在异步程序中(比如在nodejs),在下一步程序中,需要异步返回的结果,由于是异步,下一步会在异步返回前就会执行完,这时程序就会出现不是我们预想的结果。而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函数调用和普通方法一样

4. 语法

① async 函数返回一个promise 对象。
② async函数内部return语句返回的值,会成为then方法回调函数的参数。
③ async函数的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;




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值