千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

首页 视频教程 培训课程 师资团队 技术干货 常见问题 面试题 职场就业 零基础学Java 行业资讯
【热点话题】 Java技术干货 Java学习教程 Java学习笔记 Java面试题 Java培训问答 Java培训机构哪些好 Java职场就业
当前位置:Java培训  >  前端技术干货  >  关于JavaScript里的Async那些事儿

关于JavaScript里的Async那些事儿

来源:千锋教育
发布人:qyf
时间: 2022-12-27 16:56:02 1672131362

图片 1

  一、起源

  JavaScript 编程中最困难的就是异步操作,所以一直有群技术大牛试图搬开这块巨石,以达到一劳永逸的效果。

  向前追溯,从回调函数,到 Promise 对象,再到 Generator 函数,虽然能撬动这块巨石,但就是移不开或者说留

  下一个大坑,让后人苦不堪言。由于它们抽象的底层机制和复杂性,都使得人们在这条路上寸步难行。

  佛说:异步编程的最高境界,就是根本不用关心它是不是异步。

  所以就算是异步I/O只是读取一个文件而已,但也要做到精益求精。

  直到ES2017 标准引入了 async 函数,方才使异步操作变得更加方便。

  二、我是谁?

  我是async 函数,是 Generator 函数的语法糖,也就是他的简便方法。

  用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());

  };

  化身为async 函数,就是下面这样。

  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 函数就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成 await。

  三、async 函数的优点

  async 函数对 Generator 函数的改进,体现在以下三点。

  (1)内置执行器。 Generator 函数的执行必须靠执行器,所以才有了 co 函数库,而 async 函数自带执行器。使其步入普通函数的行列,一行执行

  var result = asyncReadFile();

  (2)更好的语义。 async 和 await,比起星号和 yield,语义更清楚了。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。

  (3)更广的适用性。 co 函数库约定,yield 命令后面只能是 Thunk 函数或 Promise 对象,而 async 函数的 await 命令后面,可以跟 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。

  (4)返回值是promise。这比Generator 返回函数是Iterator对象方便许多,直接可用then实现进一步操作,然后我们就会使用到then的语法糖await命令。

  四、使用场景

  原始的写法

图片 2

  使用promise方法

图片 3

  编辑切换为居中

  添加图片注释,不超过 140 字(可选)

  使用async和await方法

图片 4

  编辑切换为居中

  添加图片注释,不超过 140 字(可选)

  五、万一报错,那么...

  注意:await 命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try...catch 代码块中。

  await 命令只能用在 async 函数之中,如果用在普通函数,就会报错。

  async function dbFuc(db) {

  let docs = [{}, {}, {}];

  // 报错

  docs.forEach(function (doc) {

  await db.post(doc);

  });

  }

  上面代码会报错,因为 await 用在普通函数之中了。但是,如果将 forEach 方法的参数改成 async 函数,也有问题。

  async function dbFuc(db) {

  let docs = [{}, {}, {}];

  // 可能得到错误结果

  docs.forEach(async function (doc) {

  await db.post(doc);

  });

  }

  上面代码可能不会正常工作,原因是这时三个 db.post 操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用 for 循环。

  async function dbFuc(db) {

  let docs = [{}, {}, {}];

  for (let doc of docs) {

  await db.post(doc);

  }

  }

  如果确实希望多个请求并发执行,可以使用 Promise.all 方法。

  async function dbFuc(db) {

  let docs = [{}, {}, {}];

  let promises = docs.map((doc) => db.post(doc));

  let results = await Promise.all(promises);

  console.log(results);

  }

  // 或者使用下面的写法

  async function dbFuc(db) {

  let docs = [{}, {}, {}];

  let promises = docs.map((doc) => db.post(doc));

  let results = [];

  for (let promise of promises) {

  results.push(await promise);

  }

  console.log(results);

  }

  - End -

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

猜你喜欢LIKE

最新文章NEW

相关推荐HOT

更多>>