0
点赞
收藏
分享

微信扫一扫

【ES】157-重温基础:ES8系列(一)

【ES】157-重温基础:ES8系列(一)_c函数

ES8系列目录

  • async函数
  • 2 Promise.prototype.finally()
  • 3 Object.values(),Object.entries()
  • 4 Object.getOwnPropertyDescriptors()
  • 5 字符串填充 padStart和padEnd
  • 6 函数参数列表与调用中的尾部逗号
  • 7 共享内存与原子操作

所有整理的文章都收录到我《Cute-JavaScript》系列文章中,访问地址:http://js.pingan8787.com


1 async函数

1.1 介绍

ES8引入 ​async​函数,是为了使异步操作更加方便,其实它就是Generator函数的语法糖。
​​async​函数使用起来,只要把Generator函数的(*)号换成 ​async​​, ​yield​​换成 ​await​即可。对比如下:

  1. // Generator写法
  2. const fs = require('fs');
  3. const readFile = function (fileName) {
  4.  return new Promise(function (resolve, reject) {
  5.    fs.readFile(fileName, function(error, data) {
  6.      if (error) return reject(error);
  7.      resolve(data);
  8.    });
  9.  });
  10. };
  11. const gen = function* () {
  12.  const f1 = yield readFile('/etc/fstab');
  13.  const f2 = yield readFile('/etc/shells');
  14.  console.log(f1.toString());
  15.  console.log(f2.toString());
  16. };

  17. // async await写法
  18. const asyncReadFile = async function () {
  19.  const f1 = await readFile('/etc/fstab');
  20.  const f2 = await readFile('/etc/shells');
  21.  console.log(f1.toString());
  22.  console.log(f2.toString());
  23. };

对比Genenrator有四个优点:

  • (1)内置执行器 Generator函数执行需要有执行器,而 ​async​​函数自带执行器,即 ​​async​​函数与普通函数一模一样:
  1. async f();
  • (2)更好的语义 ​async​​和 ​​await​​,比起 ​​星号​​和 ​​yield​​,语义更清楚了。 ​​async​​表示函数里有异步操作, ​​await​​表示紧跟在后面的表达式需要等待结果。
  • (3)更广的适用性 ​yield​​命令后面只能是 Thunk 函数或 Promise 对象,而 ​​async​​函数的 ​​await​​命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
  • (4)返回值是Promise ​async​​函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用 ​​then​​方法指定下一步的操作。

进一步说, ​async​​函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而 ​await​​命令就是内部 ​then​命令的语法糖。

1.2 基本用法

async​​函数返回一个Promise对象,可以使用 ​then​​方法添加回调函数,函数执行时,遇到 ​await​就会先返回,等到异步操作完成,在继续执行。

  1. async function f(item){
  2.    let a = await g(item);
  3.    let b = await h(item);
  4.    return b;
  5. }
  6. f('hello').then(res => {
  7.    console.log(res);
  8. })

async​​表明该函数内部有异步操作,调用该函数时,会立即返回一个Promise对象。
另外还有个定时的案例,指定时间后执行:

  1. function f (ms){
  2.    return new Promise(res => {
  3.        setTimeout(res, ms);
  4.    });
  5. }
  6. async function g(val, ms){
  7.    await f(ms);
  8.    console.log(val);
  9. }
  10. g('leo', 50);

async​函数还有很多使用形式:

  1. // 函数声明
  2. async function f (){...}

  3. // 函数表达式
  4. let f = async function (){...}

  5. // 对象的方法
  6. let a = {
  7.    async f(){...}
  8. }
  9. a.f().then(...)

  10. // Class的方法
  11. class c {
  12.    constructor(){...}
  13.    async f(){...}
  14. }

  15. // 箭头函数
  16. let f = async () => {...}

1.3 返回Promise对象

async​​内部 ​return​​返回的值会作为 ​then​​方法的参数,另外只有 ​async​​函数内部的异步操作执行完,才会执行 ​then​方法指定的回调函数。

  1. async function f(){
  2.    return 'leo';
  3. }
  4. f().then(res => { console.log (res) }); // 'leo'

async​​内部抛出的错误,会被 ​catch​接收。

  1. async function f(){
  2.    throw new Error('err');
  3. }
  4. f().then (
  5.    v => console.log(v),
  6.    e => console.log(e)
  7. )
  8. // Error: err

1.4 await命令

通常 ​await​后面是一个Promise对象,如果不是就返回对应的值。

  1. async function f(){
  2.    return await 10;
  3. }
  4. f().then(v => console.log(v)); // 10

我们常常将 ​asyncawait​​和 ​try..catch​​一起使用,并且可以放多个 ​await​命令,也是防止异步操作失败因为中断后续异步操作的情况。

  1. async function f(){
  2.    try{
  3.        await Promise.reject('err');
  4.    }catch(err){ ... }
  5.    return await Promise.resolve('leo');
  6. }
  7. f().then(v => console.log(v)); // 'leo'

1.5 使用注意

  • (1) ​await​​命令放在 ​​try...catch​​代码块中,防止Promise返回 ​​rejected​​。
  • (2)若多个 ​await​后面的异步操作不存在继发关系,最好让他们同时执行。
  1. // 效率低
  2. let a = await f();
  3. let b = await g();

  4. // 效率高
  5. let [a, b] = await Promise.all([f(), g()]);
  6. // 或者
  7. let a = f();
  8. let b = g();
  9. let a1 = await a();
  10. let b1 = await b();
  • (3) ​await​​命令只能用在 ​​async​​函数之中,如果用在普通函数,就会报错。
  1. // 错误
  2. async function f(){
  3.    let a = [{}, {}, {}];
  4.    a.forEach(v =>{  // 报错,forEach是普通函数
  5.        await post(v);
  6.    });
  7. }

  8. // 正确
  9. async function f(){
  10.    let a = [{}, {}, {}];
  11.    for(let k of a){
  12.        await post(k);
  13.    }
  14. }

2 Promise.prototype.finally()

finally()​是ES8中Promise添加的一个新标准,用于指定不管Promise对象最后状态(是 ​fulfilled​​还是 ​rejected​​)如何,都会执行此操作,并且 ​finally​​方法必须写在最后面,即在 ​then​​和 ​catch​方法后面。

  1. // 写法如下:  
  2. promise
  3.    .then(res => {...})
  4.    .catch(err => {...})
  5.    .finally(() => {...})

finally​方法常用在处理Promise请求后关闭服务器连接:

  1. server.listen(port)
  2.    .then(() => {..})
  3.    .finally(server.stop);

本质上,finally方法是then方法的特例:

  1. promise.finally(() => {...});

  2. // 等同于
  3. promise.then(
  4.    result => {
  5.        // ...
  6.        return result
  7.    },
  8.    error => {
  9.        // ...
  10.        throw error
  11.    }
  12. )

【ES】157-重温基础:ES8系列(一)_异步操作_02


举报

相关推荐

0 条评论