详细学习参考文档: 阮一峰老师的博客,覆盖知识点ES6/7/8/9,本篇学习笔记对阮老师的关于async/await文档中的知识点进行分点总结

在ES8中加入async/await新特性后,很明显带来的好处是避免回调地狱,代码更加优雅,可读性远远提升。

语法

async函数的语法规则总体上比较简单,难点是错误处理机制。语法总结主要分为以下几点:

1.async函数返回一个 Promise 对象。async函数内部return语句返回的值,会成为then方法回调函数的参数。

async function f() {
return 'hello world';
} f().then(v => console.log(v))
// "hello world"

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

async function fun() {
throw new Error('啊,出错啦');
} fun().then(
v => console.log(v),
e => console.log(e)
)
// Error: 啊,出错啦

3.async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。

async function getTitle(url) {
let response = await fetch(url);
let html = await response.text();
return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle('https://tc39.github.io/ecma262/').then(console.log)
// "ECMAScript 2017 Language Specification"

4.正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。

async function f() {
// 等同于
// return 123;
return await 123;
} f().then(v => console.log(v))
// 123

5.另一种情况是,await命令后面是一个thenable对象(即定义then方法的对象),那么await会将其等同于 Promise 对象。

class Sleep {
constructor(timeout) {
this.timeout = timeout;
}
then(resolve, reject) {
const startTime = Date.now();
setTimeout(
() => resolve(Date.now() - startTime),
this.timeout
);
}
} (async () => {
const actualTime = await new Sleep(1000);
console.log(actualTime);
})();

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

async function f() {
await Promise.reject('出错了');
} f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了

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

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

错误处理

1.捕获整个async/await函数的错误

async function charCountAdd(data1, data2) {
const d1=await charCount(data1);
const d2=await charCount(data2);
return d1+d2;
}
charCountAdd('Hello','Hi')
.then(console.log)
.catch(console.log);//捕捉整个async/await函数的错误

这种方式可以捕捉整个charCountAdd运行过程中出现的错误,错误可能是由charCountAdd本身产生的,也可能是由对data1的计算中或data2的计算中产生的。

2.捕捉单个的await表达式的错误

async function charCountAdd(data1, data2) {
const d1=await charCount(data1)
.catch(e=>console.log('d1 is null'));
const d2=await charCount(data2)
.catch(e=>console.log('d2 is null'));
return d1+d2;
}
charCountAdd('Hello','Hi')
.then(console.log)
.catch(console.log);//捕捉整个async/await函数的错误

通过这种方式可以捕捉每一个await表达式的错误,如果既要捕捉每一个await表达式的错误,又要捕捉整个charCountAdd函数的错误,可以在调用charCountAdd的时候加个catch。

3.同时捕捉多个的await表达式的错误

async function charCountAdd(data1, data2) {
let d1,d2;
try {
d1=await charCount(data1);
d2=await charCount(data2);
}catch (e){
console.log('d1 is null');
}
return d1+d2;
}
charCountAdd('Hello','Hi')
.then(console.log); function charCount(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data.length);
}, 1000);
});
}

async/await的几种应用场景

1.获取异步函数的返回值,异步函数本身会返回一个Promise,所以我们可以通过then来获取异步函数的返回值。

async function charCountAdd(data1, data2) {
const d1=await charCount(data1);
const d2=await charCount(data2);
return d1+d2;
}
charCountAdd('Hello','Hi').then(console.log);//通过then获取异步函数的返回值。
function charCount(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data.length);
}, 1000);
});
}

2.async/await在并发场景中的应用

对于上述的例子,我们调用await两次,每次都是等待1秒一共是2秒,效率比较低,而且两次await的调用并没有依赖关系,那能不能让其并发执行呢,答案是可以的,接下来我们通过Promise.all来实现await的并发调用。

async function charCountAdd(data1, data2) {
const [d1,d2]=await Promise.all([charCount(data1),charCount(data2)]);
return d1+d2;
}
charCountAdd('Hello','Hi').then(console.log);
function charCount(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data.length);
}, 1000);
});
}

实现原理

async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里。

async function fn(args) {
// ...
} // 等同于 function fn(args) {
return spawn(function* () {
// ...
});
}

spawn函数的实现

function spawn(genF) {
return new Promise(function(resolve, reject) {
const gen = genF();
function step(nextF) {
let next;
try {
next = nextF();
} catch(e) {
return reject(e);
}
if(next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}

ES8之async/await学习随笔的更多相关文章

  1. C# async await 学习笔记2

    C# async await 学习笔记1(http://www.cnblogs.com/siso/p/3691059.html) 提到了ThreadId是一样的,突然想到在WinForm中,非UI线程 ...

  2. Async/Await 学习与示例

    参考:Async/await学习 es 7 提供了对 promise 对象的更好的操作,省去了很多丧心病狂的链式异步请求,promise 是回调地狱的福音,而 Async/Await 则是 promi ...

  3. async/await学习笔记

    async/await 的目的是简化使用 promises 的写法.     让我们来看看下面的例子: // 一个标准的 JavaScript 函数 function getNumber1() { r ...

  4. C# .net async await 学习

    async/await简单介绍 在处理比较耗时的操作(如图片处理.数据压缩.http请求等)传统的异步方法是直接使用Thread或者Task进行操作,在复杂的应用编写中可能会出现回调的问题,因此C#目 ...

  5. 03-es6语法 Promise 和 es8语法 async await 的了解和基本使用

    //Promise // 1.说明 : Promise 是 es6 中提出的新语法 // 2.作用 : 用 '用户编写同步代码' 的方式 '处理异步' 的一种解决方案 // 3.以前 : 处理异步 , ...

  6. C# async await 学习笔记1

    由于我的开发工具为vs.net 2010(.net 4.0),需先做以下两步才能进行: 1.下载并安装Async CTP (http://www.microsoft.com/en-us/downloa ...

  7. ES7/8新特性学习随笔

    随着每年EcmaScript都会为js带来一些新特性,带来更多美化的编程体验,今天就走进一下es2016/2017所带来的新特性 ES7新特性 includes() 指数操作符 ES8新特性 asyn ...

  8. C# async await 死锁问题总结

    可能发生死锁的程序类型 1.WPF/WinForm程序 2.asp.net (不包括asp.net mvc)程序 死锁的产生原理 对异步方法返回的Task调用Wait()或访问Result属性时,可能 ...

  9. JavaScript基础——深入学习async/await

    本文由云+社区发表 本篇文章,小编将和大家一起学习异步编程的未来--async/await,它会打破你对上篇文章Promise的认知,竟然异步代码还能这么写! 但是别太得意,你需要深入理解Promis ...

随机推荐

  1. 【洛谷P1828】香甜的黄油

    题目大意:给定 N 个点,M 条边的无向图,在其中选定 P 个点,每个点可能被选多次,求图中的一个点到选定的 P 个点的距离的值最小是多少. 题解:由于数据范围的限制,直接 Floyd 会超时,因此对 ...

  2. MySQL命令行查询乱码解决办法

    MySQL会出现中文乱码的原因不外乎下列几点: 1.server本身设定问题,例如还停留在latin1 2.table的语系设定问题(包含character与collation) 3.客户端程式(例如 ...

  3. POJ 3710 无向图简单环树上删边

    结论题,这题关键在于如何转换环,可以用tarjan求出连通分量后再进行标记,也可以DFS直接找到环后把点的SG值变掉就行了 /** @Date : 2017-10-23 19:47:47 * @Fil ...

  4. jenkins设置CSRF 协议(CRUMB值设置)

    在关闭“”调用出现Error 403 No valid crumb was included in the request 第一种解决方式是 关闭 csrf,如上图,去掉勾就可以,但是并不推荐. 第二 ...

  5. 关于SQL注入,你应该知道的那些事

    戴上你的黑帽,现在我们来学习一些关于SQL注入真正有趣的东西.请记住,你们都好好地用这些将要看到的东西,好吗? SQL注入攻击因如下几点而是一种特别有趣的冒险: 1.因为能自动规范输入的框架出现,写出 ...

  6. asp.net C#母版页和内容页事件排版加载顺序生命周期

    asp.net C#母版页和内容页事件排版加载顺序生命周期 关于ASP页面Page_Load发生在事件之前而导致的问题已经喜闻乐见,对于问题的解释也很全面,但是如何解决问题则较少有人说明,我就再 简单 ...

  7. 20155306 2016-2017-2 《Java程序设计》第八周学习总结

    20155306 2016-2017-2 <Java程序设计>第八周学习总结 教材学习内容总结 第十五章 通用API 15.1 日志 java.util.loggging包提供了日志功能相 ...

  8. <header><footer>引用

    示例:http://www.w3school.com.cn/html/html_layout.asp

  9. Apache的对象复制详解

    BeanUtils.copyProperties 和 PropertyUtils.copyProperties 两个工具类都是对两个bean之前存在name相同的属性进行处理,无论是源bean或者目标 ...

  10. 跳过复制错误——sql_slave_skip_counter

    昨天不少同学讨论<小心,前方有雷 —— sql_slave_skip_counter>,有说作者在玩文字游戏,扯了那么多sql_slave_skip_counter=1不还是跳过一个事务嘛 ...