ES8之async/await学习随笔
详细学习参考文档: 阮一峰老师的博客,覆盖知识点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学习随笔的更多相关文章
- C# async await 学习笔记2
C# async await 学习笔记1(http://www.cnblogs.com/siso/p/3691059.html) 提到了ThreadId是一样的,突然想到在WinForm中,非UI线程 ...
- Async/Await 学习与示例
参考:Async/await学习 es 7 提供了对 promise 对象的更好的操作,省去了很多丧心病狂的链式异步请求,promise 是回调地狱的福音,而 Async/Await 则是 promi ...
- async/await学习笔记
async/await 的目的是简化使用 promises 的写法. 让我们来看看下面的例子: // 一个标准的 JavaScript 函数 function getNumber1() { r ...
- C# .net async await 学习
async/await简单介绍 在处理比较耗时的操作(如图片处理.数据压缩.http请求等)传统的异步方法是直接使用Thread或者Task进行操作,在复杂的应用编写中可能会出现回调的问题,因此C#目 ...
- 03-es6语法 Promise 和 es8语法 async await 的了解和基本使用
//Promise // 1.说明 : Promise 是 es6 中提出的新语法 // 2.作用 : 用 '用户编写同步代码' 的方式 '处理异步' 的一种解决方案 // 3.以前 : 处理异步 , ...
- C# async await 学习笔记1
由于我的开发工具为vs.net 2010(.net 4.0),需先做以下两步才能进行: 1.下载并安装Async CTP (http://www.microsoft.com/en-us/downloa ...
- ES7/8新特性学习随笔
随着每年EcmaScript都会为js带来一些新特性,带来更多美化的编程体验,今天就走进一下es2016/2017所带来的新特性 ES7新特性 includes() 指数操作符 ES8新特性 asyn ...
- C# async await 死锁问题总结
可能发生死锁的程序类型 1.WPF/WinForm程序 2.asp.net (不包括asp.net mvc)程序 死锁的产生原理 对异步方法返回的Task调用Wait()或访问Result属性时,可能 ...
- JavaScript基础——深入学习async/await
本文由云+社区发表 本篇文章,小编将和大家一起学习异步编程的未来--async/await,它会打破你对上篇文章Promise的认知,竟然异步代码还能这么写! 但是别太得意,你需要深入理解Promis ...
随机推荐
- (转)Maven学习总结(三)——使用Maven构建项目
孤傲苍狼 只为成功找方法,不为失败找借口! Maven学习总结(三)——使用Maven构建项目 maven作为一个高度自动化构建工具,本身提供了构建项目的功能,下面就来体验一下使用maven构建项目的 ...
- 基于asp.net + easyui框架,一步步学习easyui-datagrid——实现分页和搜索(二)
http://blog.csdn.net/jiuqiyuliang/article/details/19967031 目录: 基于asp.net + easyui框架,一步步学习easyui-data ...
- hiho_offer收割18_题解报告_差第四题
I.求逆元欧几里得方法 II.模拟细心+耐心 *本人感悟:自己的错误在于:对于这道模拟题没有耐心静下来一字一字看题,一行一行调错,一步一步调试,我要引以为戒. III.dpf[i][j][k]=max ...
- bzoj千题计划207:bzoj1879: [Sdoi2009]Bill的挑战
http://www.lydsy.com/JudgeOnline/problem.php?id=1879 f[i][j] 表示匹配了i个字符,匹配字符串的状态为j的方案数 枚举下一个字符是什么 计算加 ...
- java7,java8 中HashMap和ConcurrentHashMap简介
一:Java7 中的HashMap 结构: HashMap 里面是一个数组,然后数组中每个元素是一个单向链表.链表中每个元素称为一个Entry 实例,Entry 包含四个属性:key, value, ...
- 20155339 2016-2017-2 《Java程序设计》第5周学习总结
20155339 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 使用try.catch 使用try.catch语法,JVM会先尝试执行try区块中的代码,如 ...
- ios TextField限制输入两位小数
只需要实现textField的这个代理方法就可以实现 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange: ...
- 开放通用Api,总有你喜欢的
接口文档 目录 通用 更新记录 接口列表 一.福彩-双色球接口 指定期号中奖号码 最新中奖号码信息 获取双色球中奖信息列表 二.节假日及万年历 指定日期的节假日及万年历信息 指定多个日期的节假日及万年 ...
- scala笔记之惰性赋值(lazy)
一.lazy关键字简介 lazy是scala中用来实现惰性赋值的关键字,被lazy修饰的变量初始化的时机是在第一次使用此变量的时候才会赋值,并且仅在第一次调用时计算值,即值只会被计算一次,赋值一次,再 ...
- 前端学PHP之正则表达式函数
前面的话 正则表达式不能独立使用,它只是一种用来定义字符串的规则模式,必须在相应的正则表达式函数中应用,才能实现对字符串的匹配.查找.替换及分割等操作.前面介绍了正则表达式的基础语法,本文将详细介绍正 ...