zoukankan      html  css  js  c++  java
  • node.js的async和await

    一、async和await是什么

    ES2017 标准引入了 async 函数,使得异步操作变得更加方便,async其实本质是Generator函数的语法糖

    • async表示函数里有异步操作
    • await表示在后面的表达式需要等待结果
    • async函数返回的是一个Promise对象,可以使用then方法添加回调函数,一旦遇到await就会先返回。

    二、node异步编程演进的四个阶段

    我们来回顾一下异步编程的写法的演进过程

    第1阶段 通过回调函数

    fs.readFile('/etc/passwd', 'utf-8', function (err, data) {
      if (err) throw err;
      console.log(data);
    })
    

    这样的方式会造成嵌套过多,在调用过多的时候,就变成了下面这样的写法,传说中的callback hell

    fs.readFile(fileA, 'utf-8', function (err, data) {
        fs.readFile(fileB, 'utf-8', function (err, data) {
            fs.readFile(fileC, 'utf-8', function (err, data) {
                // ...
            });
        });
    });
    

    第2阶段 通过Promise

    Promise 对象允许将回调函数的嵌套,改成链式调用。
    采用 Promise,连续读取多个文件,写法如下。

    const readFile = function (fileName) {
      return new Promise(function (resolve, reject) {
        fs.readFile(fileName, function(error, data) {
          if (error) return reject(error);
          resolve(data);
        });
      });
    };
    

    当操作很多的时候就变成了下面这样的写法

    var readFile = require('fs-readfile-promise');
    
    readFile(fileA)
    .then(function (data) {
      console.log(data.toString());
    })
    .then(function () {
      return readFile(fileB);
    })
    .then(function (data) {
      console.log(data.toString());
    })
    .catch(function (err) {
      console.log(err);
    });
    

    这样虽然比callback好了,但是有一个问题是代码冗余,不管什么操作,看上去都是一堆then

    第3阶段 通过Generator函数

    function* asyncJob() {
      // ...其他代码
      var f = yield readFile(fileA);
      // ...其他代码
    }
    

    函数asyncJob是一个协程,协程遇到yield命令就暂停,等到执行权返回,再从暂停的地方继续往后执行,这样的写法非常像同步操作。
    要想使用yield方法,得不停地执行next()切换到下一个yeild,调用变成了下面这样

    var fs = require('fs');
    
    var readFile = function (fileName){
      return new Promise(function (resolve, reject){
        fs.readFile(fileName, function(error, data){
          if (error) return 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());
    };
    

    第4阶段 通过async和await

    async 函数本质就是 Generator 函数的语法糖
    最后演变成了下面这样的写法

    const asyncReadFile = async function () {
      const f1 = await readFile('/etc/fstab');
      const f2 = await readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
    };
    

    async和await,比起*和yield,语义更清楚了。
    async表示函数里有异步操作,await表示在后面的表达式需要等待结果
    async函数的返回值是Promise对象
    await后面,可以是Promise对象和原始类型的值(数值、字符串和布尔值,会自动转换成resolved的Promise对象)

  • 相关阅读:
    Linux内核TSS的使用
    DPL, CPL及RPL之间的关系
    Linux内存管理(深入理解Linux内核)
    Windows下安装PIL进行图像处理
    内存Zone中的pageset成员分析
    导出符号的意义
    GDI及Windows的消息机制
    kmalloc vs vmalloc
    Linux Kernel Development有关内存管理
    STL sort
  • 原文地址:https://www.cnblogs.com/chenqionghe/p/11413643.html
Copyright © 2011-2022 走看看