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

相关推荐

  • 2.8JavaScript语言的Iterable和Iterator接口

    1.Iterable接口 方法 返回值 @@iterator 返回一个实现了Iterator接口的对象。 2.Iterator接口 方法 是否必须实现 返回值 next() 必须 返回一个实现了IteratorResult接口的对象。 return() 非必须 返回一个实现了IteratorResult接口的对象。 t…

  • 2.6JavaScript引用类型之映射(Map)

    1.映射声明 与对象只能使用字符串、数字或符号作为键不同,映射可以使用任何 JavaScript 数据类型作为键。与对象一样,映射的值可以是任何数据类型。 2.访问映射 3.获取映射长度

  • 2.2JavaScript原始类型之字符串(String)

    1.单引号和双引号字符串字面量 JavaScript 语言的单引号和双引号字符串字面量语法上没有区别,所以以下一并讲解。 单引号和双引号字符串字面量支持所有转义序列。 单引号和双引号字符串字面量不支持字符串插值。 单引号和双引号字符串字面量支持在每行末尾添加一个转义字符反斜杠 \ 转义隐式的换行符从而跨多行编写一行代码…

发表回复

登录后才能评论