async函数的基本用法

1. async函数的基本形式

//函数声明asyncfunction foo() {}//函数表达式const foo = asyncfunction () {};//对象的方法let obj = { async foo() {} };

obj.foo().then(...)//Class 的方法class Storage {

constructor() {

    this.cachePromise = caches.open('avatars');

}

async getAvatar(name) {

    const cache = awaitthis.cachePromise;

    returncache.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方法捕获到

//正常返回值asyncfunction f(){

    retrun 'hello world';

}

f().then(v => console.log(v));//hello world//抛出错误asyncfunction f(){

    thrownewError('出错了');

}

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写法vargen =function* () {

  varf1 = yield readFile('/etc/fstab');

  varf2 = yield readFile('/etc/shells');

  console.log(f1.toString());

  console.log(f2.toString());

};//async写法varasyncReadFile = asyncfunction () {

  varf1 = await readFile('/etc/fstab');

  varf2 = 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

asyncfunction dbFuc(db) {

  let docs = [{}, {}, {}];

  // 报错,forEach的function是非async,不能使用awaitdocs.forEach(function (doc) {

    await db.post(doc);

  });

}//这里不需要 asyncfunction dbFuc(db) {

  let docs = [{}, {}, {}];

  // 可能得到错误结果,这样调用也不能得到正确的结果docs.forEach(asyncfunction (doc) {

    await db.post(doc);

  });

}

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

//for ofasyncfunction dbFuc(db) {

  let docs = [{}, {}, {}];

  for (let doc of docs) {

    await db.post(doc);

  }

}//map + Promise.allasyncfunction dbFuc(db) {

  let docs = [{}, {}, {}];

  let promises = docs.map((doc) => db.post(doc));

  let results = await Promise.all(promises);

  console.log(results);

}//map + for ofasyncfunction 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进行包裹,例如:

asyncfunction myFunction() {

    try {

        await somethingThatReturnsAPromise();

    } catch (err) {

        console.log(err);

    }

}

如果仅仅对一部分错误进行处理或者忽略,可以局部的进行包裹,或者对单独的promise进行catch,例如:

asyncfunction 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做为一个整体返回。

asyncfunction fn(){}//等同于function fn(){

    returnspawn(function* (){

    })

}

spawn的实现

function spawn(genF) {

    /****

    * 返回的是一个promise

    */returnnewPromise(function(resolve, reject) {

        vargen=genF();//运行Generator这个方法;/***

        * 执行下一步的方法

        * @param fn 一个调用Generator方法的next方法

        */function step(fn) {

            //如果有错误,则直接返回,不执行下面的awaittry {

            varnext=fn();

            }catch (e){

            return reject(e)

            }

            //如果下面没有yield语句,即Generator的done是trueif(next.done){

            return resolve(next.value);

            }

            Promise.resolve(next.value).then((val)=>{

                step(function(){return gen.next(val) } )

            }).catch((e)=>{

                step(function(){returngen.throw(e) } )

            })

        }

        step(function () {

            return gen.next();

        })

    });

}

参考自async的基本用法 - 看风景就 - 博客园

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351