博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
async的基本用法
阅读量:4577 次
发布时间:2019-06-08

本文共 5720 字,大约阅读时间需要 19 分钟。

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);  });}//这里不需要 asyncfunction dbFuc(db) {   let docs = [{}, {}, {}];  // 可能得到错误结果,这样调用也不能得到正确的结果  docs.forEach(async function (doc) {    await db.post(doc);  });}

2. 循环调用await可以使用for循环或for of循环

//for ofasync function dbFuc(db) {  let docs = [{}, {}, {}];  for (let doc of docs) {    await db.post(doc);  }}//map + Promise.allasync function dbFuc(db) {  let docs = [{}, {}, {}];  let promises = docs.map((doc) => db.post(doc));  let results = await Promise.all(promises);  console.log(results);}//map + for ofasync 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); // 3}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

转载于:https://www.cnblogs.com/mengff/p/9651502.html

你可能感兴趣的文章
学习进度——第十五周
查看>>
简谈-网络爬虫的几种常见类型
查看>>
File对象目录列表器
查看>>
(K)ubuntu上将分区格式化成NTFS格式
查看>>
uva 12003 Array Transformer (大规模阵列)
查看>>
mysql5.7二进制包安装方式
查看>>
装饰者模式——Java设计模式
查看>>
39.递推练习: 菲波那契数列(2)
查看>>
排序精讲
查看>>
【bzoj3172】 Tjoi2013—单词
查看>>
【uoj2】 NOI2014—起床困难综合症
查看>>
js return的用法
查看>>
子节点填充父元素除去一固定高度后的剩余高度
查看>>
[原]IOS 后台发送邮件
查看>>
(转)JAVA Calendar详解
查看>>
转: 编码,charset,乱码,unicode,utf-8与net简单释义
查看>>
C#--正则匹配
查看>>
5.30 考试修改+总结
查看>>
BA-设计施工调试流程
查看>>
C#-CLR各版本特点
查看>>