博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Callbacks, Promises and Async/Await
阅读量:7074 次
发布时间:2019-06-28

本文共 3549 字,大约阅读时间需要 11 分钟。

本文转自作者Sandeep Dinesh的文章:

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

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~

转载地址:http://tmkml.baihongyu.com/

你可能感兴趣的文章
2015年北京大学软件project学科优秀大学生夏令营上机考试---C:单词翻转面试题...
查看>>
cocos2d-x 3.0的坑有哪些
查看>>
awk条件语句
查看>>
TCP端口状态说明ESTABLISHED、TIME_WAIT
查看>>
I.MX6 android 4.2 源码下载
查看>>
md5sum 生成 经md5加密后的字符串
查看>>
PowerShell应用之-批量执行SQL脚本
查看>>
职场加薪步步高升的五大法则
查看>>
增删主键及修改表名
查看>>
Gson库使用-排序字段(ExclusionStrategy)或者修改(FieldNamingStrategy)字段
查看>>
NTFS For Mac 的特点有哪些
查看>>
新技能,利用Reflector来修改dll引用
查看>>
Java编程的逻辑 (1) - 数据和变量
查看>>
我的屌丝giser成长记-研一篇(下)
查看>>
raft 分布式协议 -- mongodb
查看>>
[TypeScript] Using Lodash in TypeScript with Typings and SystemJS
查看>>
ASP.Net MVC开发基础学习笔记(1):走向MVC模式
查看>>
虚函数可不可以是内联函数
查看>>
据说看完这21个故事的人,30岁前都成了亿万富翁
查看>>
HDOJ-4505 小Q系列故事——电梯里的爱情
查看>>