async的基本用法
1. async函数的基本形式
//函数声明
async function foo() {} //函数表达式
const foo = async function () {}; //对象的方法
let obj = { async foo() {} };
obj.foo().then(...) //Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
} const storage = new Storage();
storage.getAvatar('jake').then(…); //箭头函数
const foo = async () => {};
2. async函数的返回值总是一个Promise
无论async函数有无await操作,其总是返回一个Promise。
1. 没有显式return,相当于return Promise.resolve(undefined);
2. return非Promise的数据data,相当于return Promise.resolve(data);
3. return Promise, 会得到Promise对象本身
async总是返回Promise,因此,其后面可以直接调用then方法,
函数内部return返回的值,会成为then回调函数的参数
函数内部抛出的错误,会被then的第二个函数或catch方法捕获到
//正常返回值
async function f(){
retrun 'hello world';
} f().then(v => console.log(v));//hello world //抛出错误
async function f(){
throw new Error('出错了');
} f().then(
v => console.log(v),
e => console.log(e) //Error: 出错了
)
3. await操作符的值
[rv] = await expression(expression可以是任何值,通常是一个promise)
expression是Promise,rv等于Promise兑现的值,若Promise被拒绝,则抛出异常,由catch捕获
expression是非Promise,会被转换为立即resolve的Promise,rv等于expression
await操作只能用在async函数中,否则会报错。
4. async就是generator和promise的语法糖
//generator写法
var gen = function* () {
var f1 = yield readFile('/etc/fstab');
var f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
}; //async写法
var asyncReadFile = async function () {
var f1 = await readFile('/etc/fstab');
var f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
async就是将 generator的 * 换成 async,将 yield 换成 await。
5. async对generator的改进
1. 内置执行器
Generator必须依靠执行器调用next方法来自动执行,例如co模块。而async函数自带执行器,可以自动执行。
2. 更好的语义
async和await分别表示异步和等待,语义更加明确
3. 适用性更强
co模块后面只能是Thunk函数或Promise对象,而await后面可以是Promise或基本数据类型(如:数字,字符串,布尔等)
4. 返回Promise,可以继续操作
async函数总是返回一个Promise对象,可以对其进行then调用,继续操作后面的数据,因此,
async函数完全可以看作是多个Promise合成一个Promise对象,而await命令就是内部的then调用。
6. async内部的并行调用
async配合await都是串行调用,但是若有并行调用,则应按照以下方式来写:
1. 变量分别接收Promise
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise();
let bar = await barPromise();
2. 使用Promise.all
let [foo,bar] = await Promise.all([getFoo(),getBar()]);
Promise.all这种写法有缺陷,一个调用报错,会终止,这个不太符合并行调用的初衷。
3. 使用多个async函数
实际上,一个async函数内部包含的调用应该是强相关的,没有依赖关系的函数调用不应该放在一个async函数中,分开来逻辑更清晰。
4. 并行执行的一些写法
1. 不能再内部非async function中使用await
async function dbFuc(db) {
let docs = [{}, {}, {}];
// 报错,forEach的function是非async,不能使用await
docs.forEach(function (doc) {
await db.post(doc);
});
}
//这里不需要 async
function dbFuc(db) {
let docs = [{}, {}, {}];
// 可能得到错误结果,这样调用也不能得到正确的结果
docs.forEach(async function (doc) {
await db.post(doc);
});
}
2. 循环调用await可以使用for循环或for of循环
//for of
async function dbFuc(db) {
let docs = [{}, {}, {}]; for (let doc of docs) {
await db.post(doc);
}
} //map + Promise.all
async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) => db.post(doc)); let results = await Promise.all(promises);
console.log(results);
} //map + for of
async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) => db.post(doc)); let results = [];
for (let promise of promises) {
results.push(await promise);
}
console.log(results);
} //for循环中去请求网页,若await操作成功,会break退出;若失败,会catch捕获,进入下一轮循环
const superagent = require('superagent');
const NUM_RETRIES = 3; async function test() {
let i;
for (i = 0; i < NUM_RETRIES; ++i) {
try {
await superagent.get('http://google.com/this-throws-an-error');
break;
} catch(err) {}
}
console.log(i); //
} test();
7. async的错误处理
使用try...catch进行包裹,例如:
async function myFunction() {
try {
await somethingThatReturnsAPromise();
} catch (err) {
console.log(err);
}
}
如果仅仅对一部分错误进行处理或者忽略,可以局部的进行包裹,或者对单独的promise进行catch,例如:
async function myFunction() {
await somethingThatReturnsAPromise().catch((err)=> {
console.log(err);
})
}
async function myFunction() {
try{
await somethingThatReturnsAPromise();
}
catch(e){}
await somethingElse();
}
Promise的错误处理,推荐用async + await来写:
// 存值
createData(title, successBack, errorBack) {
// 使用key保存数据
storage.save({
key: title,
data: 'true',
}).then(successBack(), errorBack());
}
改写为
//存值
async createData1(title, successBack, errorBack) {
try {
// 使用key保存数据
await storage.save({
key: title,
data: 'true',
});
successBack()
} catch (e) {
errorBack()
}
}
形式上更加清晰一些。
8. async函数的实现原理
async函数就是将执行器和Generator做为一个整体返回。
async function fn(){}
//等同于
function fn(){
return spawn(function* (){
})
}
spawn的实现
function spawn(genF) {
/****
* 返回的是一个promise
*/
return new Promise(function(resolve, reject) {
var gen=genF(); //运行Generator这个方法;
/***
* 执行下一步的方法
* @param fn 一个调用Generator方法的next方法
*/
function step(fn) {
//如果有错误,则直接返回,不执行下面的await
try {
var next=fn();
}catch (e){
return reject(e)
}
//如果下面没有yield语句,即Generator的done是true
if(next.done){
return resolve(next.value);
}
Promise.resolve(next.value).then((val)=>{
step(function(){ return gen.next(val) } )
}).catch((e)=>{
step(function(){ return gen.throw(e) } )
})
}
step(function () {
return gen.next();
})
});
}
参考:https://segmentfault.com/a/1190000008677697
https://juejin.im/post/5b56837c6fb9a04fe0181555
https://www.cnblogs.com/goloving/p/8013119.html
https://blog.csdn.net/u011272795/article/details/80197481
async的基本用法的更多相关文章
- async和await用法
原文:async和await用法 要理解async和await的用法,首先要了解Task相关知识,这里不做说明,因为这不是本文的重点. 如果你已经对Task很了解,那么如何使用async和await, ...
- async和await用法(Task)
原文:async和await用法 要理解async和await的用法,首先要了解Task相关知识,这里不做说明,因为这不是本文的重点. 如果你已经对Task很了解,那么如何使用async和await, ...
- @Async的简单用法总结
前言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时 候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spring 3 ...
- 浅谈async函数await用法
今天状态不太好,睡久了懵一天. 以前只是了解过async函数,并还没有很熟练的运用过,所以先开个坑吧,以后再结合实际来更新下,可能说的有些问题希望大家指出. async和await相信大家应该不陌生, ...
- Thread&ThreadPool、Parallel、Async和Await用法总结
1.线程和线程池Thread&ThreadPool //线程初始化时执行方法可以带一个object参数,为了传入自定义参数,所以执行需单独调用用于传参. Console.WriteLine(& ...
- C++11中async中future用法(一)
async意味着异步执行代码,看如下示例: #include <future> #include <thread> #include <chrono> #inclu ...
- C# Async与Await用法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- C# 异步操作 async await 的用法
1. async与 await 成对出现 async 在方法前使用 ,方法体面面用 await . 2. 使用async 和await定义异步方法不会创建新线程. 3.await 后面一定是一个扫行 ...
- async & await 的用法
async 和 await 出现在C# 5.0之后,给并行编程带来了不少的方便,特别是当在MVC中的Action也变成async之后,有点开始什么都是async的味道了.但是这也给我们 编程埋下了一些 ...
- c# async和await 用法(阻塞与不阻塞)
void PagePaint() { Console.WriteLine("Paint Start"); Paint(); Console.WriteLine("Pain ...
随机推荐
- 生鲜水果商城PC手机微信完整版源码2018版(免费)
采用php+mysql架构,含有PC.手机.微信三端,只需要修改一下数据库配置,并恢复一下数据即可使用,还有微信.支付宝等接口,如有问题请在文章下面留言一下,我看到会协助一下的,下载包里面含有详细的安 ...
- apache+php+mysql开发环境搭建
一.Apache 因为Apache官网只提供源代码,如果要使用必须得自己编译,这里我选择第三方安装包Apache Lounge. 进入Apachelounge官方下载地址:http://w ...
- 通过 zxing 生成二维码
二维码现在随处可见,在日常的开发中,也会经常涉及到二维码的生成,特别是开发一些活动或者推广方面的功能时,二维码甚至成为必备功能点.本文介绍通过 google 的 zxing 包生成带 logo 的二维 ...
- Charles使用及mock数据
1.下载charles 3.9.2[破解版地址:https://download.csdn.net/my] 下方有一种方法可破解4.2以前的版本 // Charles Proxy License // ...
- Linux命令应用大词典-第3章 文本编辑器
3.1 vi:文本编辑器 3.2 nano:编辑器 3.3 view:文办编辑器 3.4 ex:文本编辑器 3.5 ed:文本编辑器 3.6 red:文本编辑器 3.1 vi:文本编辑器 1.对文本创 ...
- Unity热更新文件的服务器部署(IIS)
1.VS新建一个"ASP.NET空网站" 工程结构如下 最好设置.Net FrameWork版本为 V4.0或者V4.5版本的,因为我们的程序最后是要部署到阿里云的虚拟服务器上的, ...
- 【icon】 图标组件说明
小程序默认了几种类型图标,其组件原型如下: <icon type="[success | success_no_circle | info | warn | waiting | can ...
- LeetCode - 231. Power of Two - 判断一个数是否2的n次幂 - 位运算应用实例 - ( C++ )
1.题目:原题链接 Given an integer, write a function to determine if it is a power of two. 给定一个整数,判断该整数是否是2的 ...
- 软工实践Alpha冲刺(3/10)
队名:我头发呢队 组长博客 作业博客 杰(组长) 过去两天完成了哪些任务 继续翻阅Google Material Design 2的官方文档 接下来的计划 音源爬取 还剩下哪些任务 app开发 燃尽图 ...
- alpha阶段个人总结(201521123031林庭亦)
一.个人总结 第一部分:硬的问题 第二部分:软的问题,在成长路上学到了什么? 1 当你看到不靠谱的设计.糟糕的代码.过时的文档和测试用例的时候,不要想 "既然别人的代码已经这样了,我的代码也 ...