2.11JavaScript语言的异步函数

1.异步函数声明

如果您想声明一个异步函数,只需要首先在普通函数前添加一个 async 关键字,然后在函数体内至少包含一个 await 关键字即可。普通函数支持函数声明、函数表达式、箭头函数、立即调用的函数表达式和实例方法。

//函数声明
async function 函数名(形参) {
  await 表达式;
}

//函数表达式
//命名函数
let 变量名 = async function 函数名(形参) {
  await 表达式;
};
//匿名函数
let 变量名 = async function(形参) {
  await 表达式;
};

//箭头函数
let 变量名 = async (形参) => {
  await 表达式;
};

//立即调用的函数表达式
//匿名函数形式
(async function(形参) {
  await 表达式;
})(实参);
//箭头函数形式
(async (形参) => {
  await 表达式;
})(实参);

//实例方法
class 类名 {
  async 方法名(形参) {
    await 表达式;
  }
}

2.await表达式

await 表达式;

await 关键字后的表达式可以是 实现了 Thenable 接口的对象、Promise 对象、普通的值。await 关键字会“解包”其后的表达式,相当于 Promise.prototype.then() 实例方法。

2.1表达式为实现了Thenable接口的对象

async function f() {
  const thenable = {
    then(resolve) {
      resolve('foo');
    }
  }
  console.log(await thenable);
}

f();  //输出: foo

2.2表达式为Promise对象

await 后跟一个 Promise 对象 p 时,表达式 await p 会一直等到 p 落定(settled)。如果 p 被兑现(fulfilled),表达式 await p 的值就是 p 的解决值。如果 p 被拒绝(rejected),表达式 await p 的值就是 p 的拒绝理由,通常情况下,拒绝理由会被作为 Error 对象抛出。

await 关键字后通常不会跟一个保存 Promise 对象的变量名,而是会跟一个返回 Promise 对象的函数调用。

//兑现
function resolveAfter2Seconds(x) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f() {
  const x = await resolveAfter2Seconds(10);
  console.log(x);
}

f();  //输出: 10
//拒绝
async function f() {
  try {
    const x = await Promise.reject(new Error("rejected!"));
  } catch (err) {
    alert(err);
  }
}

f();  //弹窗:Error: rejected!

2.3表达式为普通的值

如果 await 关键字后跟普通的值,则会被 Promise.resolve() 包装成一个兑现(fulfilled)的 Promise 对象来处理。

//原始类型
async function f() {
  console.log(await 'foo');
}

f();  //输出: foo
//引用类型
async function f() {
  console.log(await ['foo']);
}

f();  //输出: ['foo']

即使 await 关键字后面跟的是一个立即可用的普通值,但也不会被同步求值,而是会被异步求值。

async function f() {
  console.log(2);
  await null;
  console.log(4);
}

console.log(1);
f();
console.log(3);

//输出
1
2
3
4

3.异步函数的返回值

async 函数的返回值可以是 实现了 Thenable 接口的对象、Promise 对象、普通的值。Promise.prototype.then() 实例方法会“解包”返回值。

3.1返回值为实现了Thenable接口的对象

async function f() {
  const thenable = {
    then(resolve) {
      resolve('foo');
    }
  };

  return thenable;
}

f().then(console.log);  //输出: foo

3.2返回值为Promise对象

//兑现
async function f() {
  return Promise.resolve('foo');
}

f().then(console.log);  //输出: foo
//拒绝
async function f() {
  return Promise.reject(new Error("rejected!"));
}

f().catch(alert);  //弹窗: Error: rejected!

3.3返回值为普通的值

如果 async 函数返回值为普通的值(return 后无表达式 或 根本没有 return,则返回值为 undefined ),则这个值会被 Promise.resolve() 包装成一个已经兑现(fulfilled)的 Promise 对象来处理。

//原始类型(return后有表达式)
async function f() {
  return 6;
}

f().then(console.log);  //输出: 6
//原始类型(return后无表达式)
async function f() {
  return;
}

f().then(console.log);  //输出: undefined
//原始类型(无return)
async function myMethod() {
}

f().then(console.log);  //输出: undefined
//引用类型
async function f() {
  return ['foo'];
}

f().then(console.log);  //输出: ['foo']

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/javascript/javascriptlang/21545.html

(0)
huoxiaoqiang的头像huoxiaoqiang
上一篇 2020年9月10日 16:32
下一篇 2020年9月12日 14:52

相关推荐

发表回复

登录后才能评论