async的使用(async await用法)

admin 241 0

大家好,今天小编来为大家解答async的使用这个问题,async await用法很多人还不知道,现在让我们一起来看看吧!

一、async/await的使用

1、其实你要实现一个东西之前,最好是先搞清楚这两样东西

2、 async/await的用处就是:用同步方式,执行异步操作,怎么说呢?举个例子

3、比如我现在有一个需求:先请求完接口1,再去请求接口2,我们通常会这么做

4、或者我现在又有一个需求:先请求完接口1,再拿接口1返回的数据,去当做接口2的请求参数,那我们也可以这么做

5、其实这么做是没问题的,但是如果嵌套的多了,不免有点不雅观,这个时候就可以用 async/await来解决了

6、其实就类似于生活中的排队,咱们生活中排队买东西,肯定是要上一个人买完,才轮到下一个人。而上面也一样,在 async函数中, await规定了异步操作只能一个一个排队执行,从而达到用同步方式,执行异步操作的效果,这里注意了: await只能在async函数中使用,不然会报错哦

7、刚刚上面的例子 await后面都是跟着异步操作 Promise,那如果不接 Promise会怎么样呢?

8、可以看出,如果 await后面接的不是 Promise的话,其实是达不到排队的效果的

9、说完 await,咱们聊聊 async吧, async是一个位于function之前的前缀,只有 async函数中,才能使用 await。那 async执行完是返回一个什么东西呢?

10、可以看出, async函数执行完会自动返回一个状态为 fulfilled的Promise,也就是成功状态,但是值却是undefined,那要怎么才能使值不是undefined呢?很简单,函数有 return返回值就行了

11、可以看出,此时就有值了,并且还能使用 then方法进行输出

二、async函数的基本用法

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

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

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

   const cache= awaitthis.cachePromise;

   returncache.match(`/avatars/${name}.jpg`);

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('出错了');

   v=> console.log(v),

   e=> console.log(e)//Error:出错了)

[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。

Generator必须依靠执行器调用next方法来自动执行,例如co模块。而async函数自带执行器,可以自动执行。

async和await分别表示异步和等待,语义更加明确

co模块后面只能是Thunk函数或Promise对象,而await后面可以是Promise或基本数据类型(如:数字,字符串,布尔等)

async函数总是返回一个Promise对象,可以对其进行then调用,继续操作后面的数据,因此,

async函数完全可以看作是多个Promise合成一个Promise对象,而await命令就是内部的then调用。

async配合await都是串行调用,但是若有并行调用,则应按照以下方式来写:

let [foo,bar]= await Promise.all([getFoo(),getBar()]);

Promise.all这种写法有缺陷,一个调用报错,会终止,这个不太符合并行调用的初衷。

实际上,一个async函数内部包含的调用应该是强相关的,没有依赖关系的函数调用不应该放在一个async函数中,分开来逻辑更清晰。

1.不能再内部非async function中使用await

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

   await db.post(doc);

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

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

   await db.post(doc);

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

//for ofasyncfunction dbFuc(db){

   await db.post(doc);

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

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

  let results= await Promise.all(promises);

}//map+ for ofasyncfunction dbFuc(db){

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

  for(let promise of promises){

   results.push(await promise);

}//for循环中去请求网页,若await操作成功,会break退出;若失败,会catch捕获,进入下一轮循环const superagent= require('superagent');

  for(i= 0; i< NUM_RETRIES;++i){

    await superagent.get('http://google.com/this-throws-an-error');

使用try...catch进行包裹,例如:

     await somethingThatReturnsAPromise();

     console.log(err);

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

   await somethingThatReturnsAPromise().catch((err)=>{

       console.log(err);

     await somethingThatReturnsAPromise();

   await somethingElse();

Promise的错误处理,推荐用async+ await来写:

//存值createData(title, successBack, errorBack){

  //使用key保存数据   storage.save({

     key: title, 

     data:'true',

  }).then(successBack(), errorBack());

//存值async createData1(title, successBack, errorBack){

    //使用key保存数据     await storage.save({

       key: title, 

       data:'true',

     successBack()

     errorBack()

async函数就是将执行器和Generator做为一个整体返回。

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

   returnspawn(function*(){

  *返回的是一个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的基本用法-看风景就-博客园

三、如何使用js中async函数

这次给大家带来如何使用js中async函数,使用js中async函数的注意事项有哪些,下面就是实战案例,一起来看一下。

异步操作是 JavaScript编程的麻烦事,麻烦到一直有人提出各种各样的方案,试图解决这个问题。

从最早的回调函数,到 Promise对象,再到 Generator函数,每次都有所改进,但又让人觉得不彻底。它们都有额外的复杂性,都需要理解抽象的底层运行机制。

异步I/O不就是读取一个文件吗,干嘛要搞得这么复杂?异步编程的最高境界,就是根本不用关心它是不是异步。

async函数就是隧道尽头的亮光,很多人认为它是异步操作的终极解决方案。

一句话,async函数就是 Generator函数的语法糖。

前文有一个 Generator函数,依次读取两个文件。

var fs= require('fs');

var readFile= function(fileName){

return new Promise(function(resolve, reject){

fs.readFile(fileName, function(error, data){

var f1= yield readFile('/etc/fstab');

var f2= yield readFile('/etc/shells');

};写成 async函数,就是下面这样。

var asyncReadFile= async function(){

var f1= await readFile('/etc/fstab');

var f2= await readFile('/etc/shells');

};一比较就会发现,async函数就是将 Generator函数的星号(*)替换成 async,将 yield替换成 await,仅此而已。

三、async函数的优点async函数对 Generator函数的改进,体现在以下三点。

(1)内置执行器。 Generator函数的执行必须靠执行器,所以才有了 co函数库,而 async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。

(2)更好的语义。 async和 await,比起星号和 yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

(3)更广的适用性。 co函数库约定,yield命令后面只能是 Thunk函数或 Promise对象,而 async函数的 await命令后面,可以跟 Promise对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。

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

}所有的 async函数都可以写成上面的第二种形式,其中的 spawn函数就是自动执行器。

下面给出 spawn函数的实现,基本就是前文自动执行器的翻版。

return new Promise(function(resolve, reject){

Promise.resolve(next.value).then(function(v){

step(function(){ return gen.next(v);});

step(function(){ return gen.throw(e);});

step(function(){ return gen.next(undefined);});

}async函数是非常新的语法功能,新到都不属于 ES6,而是属于 ES7。目前,它仍处于提案阶段,但是转码器 Babel和 regenerator都已经支持,转码后就能使用。

五、async函数的用法同 Generator函数一样,async函数返回一个 Promise对象,可以使用 then方法添加回调函数。当函数执行的时候,一旦遇到 await就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

async function getStockPriceByName(name){

var symbol= await getStockSymbol(name);

var stockPrice= await getStockPrice(symbol);

getStockPriceByName('goog').then(function(result){

});上面代码是一个获取股票报价的函数,函数前面的async关键字,表明该函数内部有异步操作。调用该函数时,会立即返回一个Promise对象。

下面的例子,指定多少毫秒后输出一个值。

return new Promise((resolve)=>{

async function asyncPrint(value, ms){

asyncPrint('hello world', 50);上面代码指定50毫秒以后,输出"hello world"。

六、注意点await命令后面的 Promise对象,运行结果可能是 rejected,所以最好把 await命令放在 try...catch代码块中。

await somethingThatReturnsAPromise();

await somethingThatReturnsAPromise().catch(function(err){

}await命令只能用在 async函数之中,如果用在普通函数,就会报错。

}上面代码会报错,因为 await用在普通函数之中了。但是,如果将 forEach方法的参数改成 async函数,也有问题。

docs.forEach(async function(doc){

}上面代码可能不会正常工作,原因是这时三个 db.post操作将是并发执行,也就是同时执行,而不是继发执行。正确的写法是采用 for循环。

}如果确实希望多个请求并发执行,可以使用 Promise.all方法。

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

let results= await Promise.all(promises);

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

for(let promise of promises){

}相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

OK,本文到此结束,希望对大家有所帮助。