async/await-Promise-让异步操作同步执行

首先,要明白异步跟同步,参考下方博客的案例介绍:async/await让异步操作同步执行的方法详解 - dreamw - 博客园 (cnblogs.com)https://www.cnblogs.com/wl-blog/p/15136449.html

function fn1(){
 console.log(111)
 setTimeout(function(){
  console.log('wait me 3000')
 },3000)
}
function fn2(){
 console.log(222)
}
fn1();
fn2();

//输出结果:
//111
//222
//wait me 3000

这里的setTimeout方法就是异步操作,它会在同步操作之后才执行,所以在执行了fn1后,同步执行了fn2,最后才执行setTimeout方法

 你可能会想,这个setTimeout延时了3秒才执行,肯定比fn2慢,那下面把延时时间设为0看一下

function fn1(){
 console.log(111)
 setTimeout(function(){
  console.log('wait me 0')
 },0)
}
function fn2(){
 console.log(222)
}
fn1();
fn2();

//运行结果:
//111
//222
//wait me 0

即使设置的等待时间是0,仍然会被当作异步方法,要等到同步方法执行完才会执行它 

注意:利用setTimeout=>0这个异步特性,可以修改方法中的方法的执行顺序

function fn1(){
 console.log(111)
//通过设置setTimeout=>0,不延时执行方法,但是能将fn2放到同步方法执行完之后再执行
//也就是等到fn1,fn3执行完,再执行fn2,即使fn2再fn1中
 setTimeout(fn2,0)
}

function fn2(){
 console.log(222)
}

function fn3(){
 console.log(333)
}

fn1();
fn3();

//输出结果:
//111
//333
//222

这样,既可以不延时调用fn2方法,又可以修改fn2方法的调用顺序,在fn1方法和fn3方法执行完后再调用fn2方法。

 以上就是对异步、同步的简单举例,接下来重点说明一下如何通过async、await 或者promise.then()来讲异步操作同步化


async和await

async:它修饰的方法,返回的数据就会是个promise对象(可单独使用)

await:意思是等待执行完它修饰的方法,再往下执行,它会阻塞后面的代码,也就是同步

  • await 如果得到的是 Promise 对象,则得到其 resolve值
  • 需要配合async使用

例子1:

async function fn(){
 return '111'
}

console.log(fn());  //Promise { '111' }

或者:
fn().then(data=>{
 console.log(data)  //111
}

使用async修饰的方法就会返回promise对象,

        如果一个函数加了async关键词,这个函数又有返回值,在调用这个函数时,如果函数执行成功,内部会调用Promise.resolve()方法返回一个Promise对象,如果函数执行出现异常,就会调用Promise.reject()方法返回一个promise 对象

  • 要想获取到async函数的执行结果,就要调用Promise.then()  

例子2:

function f() {
//最好是将方法返回成promise对象,用resolve,不然些复杂的函数,会导致await没效果
    return new Promise(resolve =>{
        resolve('hhh')
    })
}
async function doSomething1(){
  let x = await f();
   return x
}

doSomething1().then(res=>{
  console.log(res)
})

打印结果:
hhh

1、函数前面会加一个async修饰符,就会证明这个函数是一个异步函数;(也就是说这里的doSomething1函数是个异步函数)

2、await 是个运算符,用于组成表达式,它会阻塞后面的代码(也就是说这里的f()函数被转换成了同步函数,即使里面有异步方法,也会执行完再往下执行)

3、await 如果得到的是 Promise 对象,则得到其 resolve值

例子3:

async function doSomething1(){
//最好是将方法返回成promise对象,用resolve,不然些复杂的函数,会导致await没效果
    let x = await 'hhh'  //这里await修饰的不是一个方法,也不是一个promise对象
    return x 
}

console.log(doSomething1())   
//Promise {} ==> async修饰的函数,就会返回promise对象

doSomething1().then(res => {
    console.log(res)   //hhh  ==> 通过.then获取到promise对象的resolve出来的值
})    



另一种情况:

async function doSomething1(){
    let x = await fn2()  //即使fn2返回的不是promise,也可以用await修饰
    return x
}

function fn2(){
 return '123456'
}

doSomething1().then(res => {  
    console.log(res)  //123456 ==>因为是用async修饰的函数,所以可以用.then获取到返回的数据
})

 1、async修饰的方法返回的是一个promise对象,其 return 返回的值,会成为 .then() 方法回调函数的参数;

2、await修饰的方法如果得到的不是promise对象,也是可以的,得到的是啥就是啥,仍然会有await的阻塞效果(同步)。

例子4:

function fn1(){
//最好是将方法返回成promise对象,用resolve,不然些复杂的函数,会导致await没效果
 return new Promise(resolve=>{
  setTimeout(function(){
   msg='wait me 3000';
   resolve(msg)
  },3000);
 });
}
async function asyncCall(){
 var result=await fn1();
 console.log(result); 
}
asyncCall();
运行结果:
三秒后,会输出: wait me 3000

        这是因为有await将fn1方法改成了同步方法,阻塞了后面的console.log(result),等到执行完fn1中的异步方法后,拿到了resolve的返回值,才去执行下一步。

async/await-Promise-让异步操作同步执行_第1张图片

        如上图所示,如果不适用async await将fn1方法转成同步方法,那么因为fn1中的异步操作会在console.log(result)这个同步方法执行完后才执行,也就没有拿到resolve的返回值,自然就会输出undefined


  注意:try catch只能用来捕获【同步函数】,不能用来捕获【异步函数】

try{ 
 fn()
}
catch(error){
 console.error(error);
}

try catch只能捕获【同步方法】的错误,如果fn是个异步方法,就会报错,捕获不到,所以,一般都是对 async await修饰的方法用try catch,因为async await修饰的方法就会变成【同步方法】


看完上面的例子,你现在应该知道,如何把函数转成同步来执行了,接下来用一个例子来说明一下:

  async function a () {
      return new Promise((resolve, reject) => {
        resolve('123456')
      })
    }
//通过async修饰后的方法,可以用.then来获取返回值
  a().then(res => {   
      console.log(res)  // 123456
  })

或者:
async function a () {
      return '123456'
    }
 a().then(res => {
      console.log(res)  //123456
 })

 通过async修饰后的方法,可以用.then来获取返回值,然后我们就可以在.then中进行下一个方法的调用了,这样既能规定好哪一个方法先执行,哪一个后执行

当然,你也可以用 await,直接把想要的方法转换成同步方法

 async a () {
//最好是将方法返回成promise对象,用resolve,不然些复杂的函数,会导致await没效果
      return new Promise((resolve, reject) => {
        resolve('123456')
      })
    }
//通过await将方法a()转成同步的,执行完a方法之后,才会往下执行
  var result=await a();
  console.log(result); 
    b()
    c()
    .....

有时候,你设置了一个async方法,然后里面return一个promise对象,然后这个对象里面还要调用一个await方法,那么【eslint规范】会报错提示:promise中不建议使用await,你可以直接利用vscode的错误修复功能,alt+.  在报错行添加一行注释,取消eslint的报错,这样就能正常运行了。

你可能感兴趣的:(async-await,异步-同步)