zl程序教程

您现在的位置是:首页 >  后端

当前栏目

JS中的 async 和 await 使用技巧

JSasync 使用 技巧 await
2023-06-13 09:18:40 时间

一、概述

案例:

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

asyncReadFile();

async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。 await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,它们会被自动转成立即 resolved 的 Promise 对象)。

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


二、基本用法

(1)async

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数。

async function f() {
  return 'hello'
}

console.log(f());      // promise对象
f().then(result => {
  console.log(result); // hello
})

async 函数内部抛出错误,会导致返回的 Promise 对象变为 rejec t状态。抛出的错误对象会被 catch 方法回调函数接收到。

async function f() {
  throw new Error('出错了')
}

f().then(result => {
  console.log(result); 
}).catch(err => {
  console.log(err); // Uncaught (in promise) Error: 出错了
})

(2)await

正常情况下,await 命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。另外,await 命令只能用在 async 函数之中,如果用在普通函数,就会报错。

async function f() {
  // 等同于
  // return 123;
  return await 123;
}

f().then(v => console.log(v))
// 123

await 命令后面的 Promise 对象如果变为 reject 状态,则 reject 的参数会被 catch 方法的回调函数接收到。等同于async函数返回的 Promise 对象被reject。

async function f() {
  await Promise.reject('出错了');
}

f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了

上面代码中,await语句前面没有return,但是reject方法的参数依然传入了catch方法的回调函数。这里如果在await前面加上return,效果是一样的。

任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。

async function f() {
  await Promise.reject('出错了');
  await Promise.resolve('hello world'); // 不会执行
}

(3)使用注意事项

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

async function myFunction() {
  try {
    await test();
  } catch (err) {
    console.log(err);
  }
}

// 另一种写法
async function myFunction() {
  await test().catch(function (err) {
    console.log(err);
  });
}

(4)案例

案例1:

async function f2() {
  let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('hello')
    },1000)
  })

  // await 后应该是一个 Promise 对象,如果不是,会被转成一个 Promise 对象
  // await必须配合 async 来使用
  let result = await promise; // 一个表达式,表达式的值就是 promise 所返回的值
  console.log(result);
  console.log(await 4);
  console.log(2);
  return 3; // 相当于:return Promise.resolve(3)
}

f2().then(result => {
  console.log(result);
})

// hello
// 4
// 2
// 3

案例2: 借助await命令就可以让程序停顿指定的时间,实现休眠效果。

function sleep(internal) {
  return new Promise(resolve => {
    setTimeout(resolve, internal);
  })
}

async function f3() {
  for (let i = 0; i < 5; i++) {
    console.log(i);
    await sleep(100);
  }
}

f3();