JavaScript中async和await的实现原理

由于javascript是单线程的执行模型,因此为了提高效率就有了异步编程,单线程在程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。 但是我们也需要类似多线程机制的这种执行方式,我们需要异步执行编程,异步执行编程会使得多个任务并发执行。 异步编程可以实现多任务并发执行,指同一时刻内多任务同时进行,边煮饭,边烧水,可以同时进行,进而提高效率。

1.回调函数

回调函数,就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。

const fs = require('fs')
fs.readFile('/etc/passwd', (err, data) => {
  if (err) {
    console.error(err)
    return
  }
  console.log(data.toString())
})

回调函数最大的问题是容易形成回调地狱,即多个回调函数嵌套,降低代码可读性,增加逻辑的复杂性,容易出错。

fs.readFile(file1, function (err, data) {
  fs.readFile(file2, function (err, data) {
    // 
  })
})

2.promise

为解决回调函数的不足,就有了Promise。

const fs = require('fs')

const readFileWithPromise = file => {
  return new Promise((resolve, reject) => {
    fs.readFile(file, (err, data) => {
      if (err) {
        reject(err)
      } else {
        resolve(data)
      }
    })
  })
}

readFileWithPromise('/etc/passwd')
  .then(data => {
    console.log(data.toString())
    return readFileWithPromise('/etc/profile')
  })
  .then(data => {
    console.log(data.toString())
  })
  .catch(err => {
    console.log(err)
  })

 promise 实际上是利用编程技巧将回调函数的横向加载,改成纵向加载,达到链式调用的效果,避免回调地狱。最大问题是代码冗余,原来的任务被 promise 包装了一下,优点是减少代码嵌套,代码逻辑清晰。

3.async、await

为了解决 promise 的问题,async、await 在 ES7 中被提了出来

const fs = require('fs')
async function readFile() {
  try {    
    var f1 = await readFileWithPromise('/etc/passwd')
    console.log(f1.toString())
    var f2 = await readFileWithPromise('/etc/profile')
    console.log(f2.toString())
  } catch (err) {
    console.log(err)
  }
}

特点:

1.异步async函数的调用,跟普通的函数使用方式一样;

2.async的用法,它作为一个关键字放到函数前面,这样普通函数就变成了异步函数;

3.异步async函数返回一个promise对象;

4.async函数配合await使用可以阻塞代码往下执行,是异步方法。

优点:

1.多个参数传递:promise使用then函数只能传递一个参数,虽然可以通过包装成对象来传递多个参数,但是会导致传递冗余信息,频繁的解析又重新组合比较麻烦;而利用async和await可以没有这个限制,可以当做普通变量的局部变量来处理,也没有冗余工作;

2.同步和异步一起编写:使用promise的时候最好将同步代码和异步代码放在不同的then节点中,这样结构更加清晰;async和await整个书写习惯都是同步的,不需要纠结同步和异步的区别,当然,异步过程需要包装成一个promise对象放在await关键字后面;

3. 对promise的优化:async和await是基于promise的,是进一步的一种优化。

使用场景:

async和await主要用来处理异步的操作,执行第一步,将执行第一步的结果返回给第二步使用,在ajax中先拿到一个接口的返回数据,后使用第一部返回的数据执行第二步操作的接口调用,达到异步操作。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Promise、async和awaitJavaScript用于处理异步操作的关键字。它们的实现原理如下: 1. Promise:Promise是一种表示异步操作的对象,它包含三种状态(pending、fulfilled、rejected)。当一个异步操作完成时,Promise可从pending状态转变为fulfilled状态,表示操作成功;或者从pending状态转变为rejected状态,表示操作失败。Promise提供了then方法来处理操作的结果,并可以进行链式调用。 2. async/awaitasync函数是Generator函数的一种语法糖,用来简化异步操作的处理。通过在函数前添加async关键字,函数返回值将被自动封装成Promise对象。await关键字只能在async函数使用,用于暂停async函数的执行,等待Promise对象的状态改变后再继续执行。当await后面的异步操作完成时,它会返回Promise对象的结果。 下面以一个获取用户信息的案例来分析Promise、async和await的用法: 使用Promise实现: ``` function getUserInfo() { return new Promise((resolve, reject) => { setTimeout(() => { const user = { name: 'John', age: 25 }; resolve(user); }, 1000); }); } getUserInfo() .then(user => { console.log(user); }) .catch(error => { console.error(error); }); ``` 使用async/await实现: ``` function getUserInfo() { return new Promise((resolve, reject) => { setTimeout(() => { const user = { name: 'John', age: 25 }; resolve(user); }, 1000); }); } async function displayUserInfo() { try { const user = await getUserInfo(); console.log(user); } catch (error) { console.error(error); } } displayUserInfo(); ``` 以上两种方式都可以获取用户信息,并在操作完成后打印到控制台。使用async/await可以使代码看起来更加简洁和易读。通过在async函数内部使用await关键字,可以将异步操作的代码写成类似同步代码的形式,提高了代码的可读性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

simple-xiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值