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日
下一篇 2020年9月12日

相关推荐

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

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

  • 1.3JavaScript语言的非运算符(Non-Operator)和运算符(Operator)

    1.非运算符 非运算符 描述 空白 空格(U+0020)、水平制表符(\t,U+0009)、垂直制表符(\v,U+000B)、分页符(\f,U+000C)。 行结束符 换行符(\n,U+000A)、回车符(\r,U+000D)、行分隔符(U+2028)、段落分隔符(U+2029)。 , 逗号 ; 分号 () 圆括号 […

  • 1.6JavaScript语言的常量(Constant)

    1.常量声明 注意:在同一个作用域,常量不可以重复声明,否则会报错。 常量在赋值后不可以通过重新赋值改变其值,即使新的值与老的值相同也不可以。 然而,对象被赋值给常量后,改变对象的属性的值是可以的。 注意:属性新的值的类型不一定与属性老的值的类型相同。 2.常量声明提升(Hoisting) 常量声明不支持提升。 3.常…

发表回复

登录后才能评论