资讯专栏INFORMATION COLUMN

Callbacks, Promises and Async/Await

hss01248 / 2078人阅读

摘要:在开始之前,他们不会等待最后一个功能完成。第一个函数完成后,它将运行第二个函数。回调的问题是它创建了一个名为的东西。该函数返回此对象。再次,让我们尝试按顺序打印字母,,这被称为承诺链。该功能与版本保持一致。

本文转自作者Sandeep Dinesh的文章:Callbacks, Promises and Async/Await

假设你有一个函数可以在一段随机的时间后打印一个字符串:

function printString(string){
  setTimeout(
    () => {
      console.log(string)
    }, 
    Math.floor(Math.random() * 100) + 1
  )
}

让我们尝试按顺序打印字母A,B,C:

function printAll(){
  printString("A")
  printString("B")
  printString("C")
}
printAll()

每次调用printAll时,您会注意到A,B和C以不同的随机顺序打印!

这是因为这些函数是异步的。每个函数按顺序执行,但每个函数都独立于它自己的setTimeout。在开始之前,他们不会等待最后一个功能完成。

这非常烦人,所以让我们用回调修复它。

Callbacks

回调是传递给另一个函数的函数。第一个函数完成后,它将运行第二个函数。

function printString(string, callback){
  setTimeout(
    () => {
      console.log(string)
      callback()
    }, 
    Math.floor(Math.random() * 100) + 1
  )
}

你可以看到,修改原始函数是非常容易的,可以使用回调。

再次,让我们尝试按顺序打印字母A,B,C:

function printAll(){
  printString("A", () => {
    printString("B", () => {
      printString("C", () => {})
    })
  })
}
printAll()

嗯,代码现在很丑陋,但至少它有效!每次调用printAll时,都会得到相同的结果。

回调的问题是它创建了一个名为“Callback Hell”的东西。基本上,你开始在函数内的函数内嵌套函数,并且开始变得非常难以阅读代码。

Promise

Promise尝试修复这个嵌套问题。让我们改变我们的功能来使用Promises

function printString(string){
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
       console.log(string)
       resolve()
      }, 
     Math.floor(Math.random() * 100) + 1
    )
  })
}

你可以看到它看起来仍然非常相似。您将整个函数包装在Promise中,而不是调用回调,而是调用resolve(如果出现错误则拒绝)。该函数返回此Promise对象。

再次,让我们尝试按顺序打印字母A,B,C:

function printAll(){
  printString("A")
  .then(() => {
    return printString("B")
  })
  .then(() => {
    return printString("C")
  })
}
printAll()

这被称为承诺链。您可以看到代码返回函数的结果(将是Promise),并将其发送到链中的下一个函数。

代码不再嵌套,但看起来仍然很混乱!

通过使用箭头函数的功能,我们可以删除“包装器”功能。代码变得更清晰,但仍然有很多不必要的括号:

function printAll(){
  printString("A")
  .then(() => printString("B"))
  .then(() => printString("C"))
}
printAll()
Await

Await基本上是Promises的语法糖。它使您的异步代码看起来更像是同步/过程代码,人类更容易理解。

该PRINTSTRING功能不自许的版本在所有改变。

再次,让我们尝试按顺序打印字母A,B,C:

async function printAll(){
  await printString("A")
  await printString("B")
  await printString("C")
}
printAll()

是啊...。好多了!

您可能会注意到我们对包装函数printAll使用“async”关键字。这让我们的JavaScript知道我们正在使用async / await语法,如果你想使用Await,这是必要的。这意味着你不能在全球范围内使用Await; 它总是需要一个包装函数。大多数JavaScript代码都在函数内部运行,因此这不是什么大问题。

等等,这里还有更多哦

该PRINTSTRING函数不返回任何东西,是独立的,所有我们关心的是顺序。但是,如果您想获取第一个函数的输出,在第二个函数中执行某些操作,然后将其传递给第三个函数,该怎么办?

我们不是每次都打印字符串,而是创建一个连接字符串并传递它的函数。

Callbacks

这里是回调样式:

function addString(previous, current, callback){
  setTimeout(
    () => {
      callback((previous + " " + current))
    }, 
    Math.floor(Math.random() * 100) + 1
  )
}

为了使用它:

function addAll(){
  addString("", "A", result => {
    addString(result, "B", result => {
      addString(result, "C", result => {
       console.log(result) // Prints out " A B C"
      })
    })
  })
}
addAll()

不太好。

Promises

这是Promise风格:

function addString(previous, current){
  return new Promise((resolve, reject) => {
    setTimeout(
      () => {
        resolve(previous + " " + current)
      }, 
      Math.floor(Math.random() * 100) + 1
    )
  })
}

为了使用它:

function addAll(){  
  addString("", "A")
  .then(result => {
    return addString(result, "B")
  })
  .then(result => {
    return addString(result, "C")
  })
  .then(result => {
    console.log(result) // Prints out " A B C"
  })
}
addAll()

使用箭头函数意味着我们可以使代码更好一些:

function addAll(){  
  addString("", "A")
  .then(result => addString(result, "B"))
  .then(result => addString(result, "C"))
  .then(result => {
    console.log(result) // Prints out " A B C"
  })
}
addAll()

这肯定更具可读性,特别是如果你向链添加更多,但仍然是一堆括号。

Await

该功能与Promise版本保持一致。

并且为了使用它:

async function addAll(){
  let toPrint = ""
  toPrint = await addString(toPrint, "A")
  toPrint = await addString(toPrint, "B")
  toPrint = await addString(toPrint, "C")
  console.log(toPrint) // Prints out " A B C"
}
addAll()

Yeah. SO MUCH BETTER~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101638.html

相关文章

  • 现代JS中的流程控制:详解CallbacksPromisesAsync/Await

    摘要:控制台将显示回调地狱通常,回调只能由一个异步函数调用。更多资源使更友好规范使用异步函数简化异步编码旅程异步编程是一项在中无法避免的挑战。 JavaScript经常声称是_异步_。那是什么意思?它如何影响发展?近年来这种方法有何变化? 请思考以下代码: result1 = doSomething1(); result2 = doSomething2(result1); 大多数语言都处理每...

    shadowbook 评论0 收藏0
  • 现代JS中的流程控制:详解CallbacksPromisesAsync/Await

    摘要:控制台将显示回调地狱通常,回调只能由一个异步函数调用。更多资源使更友好规范使用异步函数简化异步编码旅程异步编程是一项在中无法避免的挑战。 JavaScript经常声称是_异步_。那是什么意思?它如何影响发展?近年来这种方法有何变化? 请思考以下代码: result1 = doSomething1(); result2 = doSomething2(result1); 大多数语言都处理每...

    oujie 评论0 收藏0
  • 现代JS中的流程控制:详解CallbacksPromisesAsync/Await

    摘要:控制台将显示回调地狱通常,回调只能由一个异步函数调用。更多资源使更友好规范使用异步函数简化异步编码旅程异步编程是一项在中无法避免的挑战。 JavaScript经常声称是_异步_。那是什么意思?它如何影响发展?近年来这种方法有何变化? 请思考以下代码: result1 = doSomething1(); result2 = doSomething2(result1); 大多数语言都处理每...

    anquan 评论0 收藏0
  • 翻译:Taming the asynchronous beast with ES7

    摘要:让我们使用它从数组中返回一个值数组在中,我们可以这样做,这是一种更简单的方法最重要的部分是创建数组,该数组立即调用所有的我们在主函数中等待这些。所以在我们真正等待完成之前,主函数就退出了。 原文:https://pouchdb.com/2015/03/0... PouchDB最棘手的方面之一是它的API是异步的。在Stack Overflow、Github和IRC上,我看到了不少困惑的...

    Eastboat 评论0 收藏0
  • promise, async, await, execution order

    摘要: async can be transformed to promise. So, if we want to understand async, we have to understand promise first. Promise Normally, promise is easy to understand, especially when using like this: p...

    neuSnail 评论0 收藏0

发表评论

0条评论

hss01248

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<