Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async 和 await #20

Open
18888628835 opened this issue Apr 29, 2021 · 0 comments
Open

async 和 await #20

18888628835 opened this issue Apr 29, 2021 · 0 comments

Comments

@18888628835
Copy link
Owner

18888628835 commented Apr 29, 2021

async和await

简单来说,它们是基于promises的语法糖,使异步代码更易于编写和阅读。通过使用它们,异步代码看起来更像是老式同步代码,因此它们非常值得学习。

async关键字

async function hello() { return "Hello" };
hello();
//Promise {<fulfilled>: "Hello"}

上面的代码增加async关键字后,这个函数会返回promise。这是异步的基础,可以说,现在的异步JS就是使用promise。

箭头函数写法

let hello=async ()=>{return 'hello'}

现在我们可以使用.then方法啦

hello().then((mes)=>{console.log(mes)})

await关键字

await只在异步函数里面才起作用,它的主动作用是会暂停代码在该行上,直到promise完成,然后返回结果值,await后面应该放promise对象

我们可以造一个实际的例子

const p=new Promise((resolve,reject)=>{
  setTimeout(resolve,3000,'doing')
})
const r=new Promise((resolve,reject)=>{
  setTimeout(resolve,0,p)
})
const o=r.then((mes)=>{
  return mes+'=>done'
})
o.then((mes)=>{console.log(mes)}).catch((error)=>{console.log(error)})
//doing => done

上面代码中,r会拿到p的结果,然后链式调用下去。

我们可以使用async+await进行封装

    function promise(ms, mes) {
      return new Promise((resolve, reject) => {
        setTimeout(resolve, ms, mes);
      });
    }
    async function fn() {
      const p = await promise(3000, "doing");
      console.log(p); // doing
      const r = await promise(0, p);
      console.log(r); //doing
      const o = await (r + "=>done");
      console.log(o); //doing =>done
    }
    fn();

可以看到上面的异步代码就跟同步代码的写法一样。

asyncawait要同时使用才会有异步的效果,单单使用async依然是同步代码,只是返回promise对象

错误处理

在使用async/await关键字的时候,错误处理是关键,一般我们会这么写来捕捉错误

function ajax(){
   return Promise.reject(1)
}
async function fn(){
   try{
      const result=await ajax()
      console.log(result)
   }catch(error){
      console.log(error)
   }
}
fn() 

下面我们可以使用更好的方法

function ajax(){
   return Promise.reject(1)
}
function ErrorHandler(error){
    throw Error(error)
}
async function fn(){
   const result=await ajax().then(null,(error)=>{ErrorHandler(error)})
   console.log('result',result)
}
fn()

这里要注意的就是ErrorHandler时不要用return,以免把结果返回给result,使用throw Error就可以抛出一个错误。那么后续的代码就不会执行了

await的传染性

function async2(){
console.log('async2')
}
async function fn(){
   console.log('fn')
   await async2() //同步的
   console.log('我是异步?')
}
fn()
console.log('end')
//fn
//async2
//end
//我是异步?

最后的console.log('我是什么步?')是后于await关键字的,说明它是异步的,如果我们想执行同步代码,最好都放在await的上面,因为有时候await会带给我们疑惑,会误以为没有写await关键字的代码是同步的。

也许你会怀疑是否第一行log也是异步的,下面这个代码可以告诉你答案,并非写了async关键字就代表这是异步函数。

let a=0
async function fn(){
   console.log(a)
   await Promise.resolve(333).then((r)=>{console.log(r)})
   console.log('我是什么步?')
}
fn()
console.log(++a)
//结果
/*
0
1
333
"我是什么步?"
*/

串行和并行

await天生是串行的,所谓串行,就是按照顺序执行。

function async2(delay){
  return new Promise((resolve)=>{
    setTimeout(()=>{
      console.log('执行')
      resolve()
    },delay)
  })
}                  
async function fn(){
  await async2(5000)
  await async2(2000)
  await async2(1000)
}
fn()

由于async跟setTimeout同时用没有效果,所以我使用上面的代码做实验,log台五秒钟后会分别打印,这说明默认就是按照顺序执行await的

如果想要并行,就可以使用Promise.all或者forEach方法

function fn(){
  await Promise.all([async2(5000),async2(2000),async2(1000)])
}
function async2(delay){
  return new Promise((resolve)=>{
    setTimeout(()=>{
      console.log('执行')
      resolve()
    },delay)
  })
}
                     
function fn3(ms){
  return function fn(){
    async2(ms)
  }
}

[fn3(5000),fn3(2000),fn3(1000)].forEach(async (v)=>{
  await v()
})

与fetch相结合

fetch就是使用promise版本的XMLHttpRequest

fetch('products.json').then(function(response) {
  return response.json();
}).then(function(json) {
  console.log(json)
}).catch(function(err) {
  console.log('Fetch problem: ' + err.message);
});

上面的代码的意思是通过fetch申请一个json数据,然后得到数据后将其json化,再打印出来。

转化成async和await方法

const promise=()=>{
  try{
     const j=await fetch('products.json')
     const result=await j.json()
     console.log(result)
  }catch(error){
     console.log(error)
  }
}
promise()

在非 async 函数中调用 async 函数

我们有一个名为 f 的“普通”函数。你会怎样调用 async 函数 wait() 并在 f 中使用其结果?

async function wait() {
  await new Promise(resolve => setTimeout(resolve, 1000));

  return 10;
}

function f() {
  // ……这里你应该怎么写?
  // 我们需要调用 async wait() 并等待以拿到结果 10
  // 记住,我们不能使用 "await"
}

其实解决方法很简单,由于 await 会返回一个 promise,所以直接在后面写 then 方法就可以拿到结果

function f() {
  wait().then(result => alert(result));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant