Express 中的回调与等待性能

Posted

技术标签:

【中文标题】Express 中的回调与等待性能【英文标题】:Callback vs Await Performance in Express 【发布时间】:2018-09-16 05:21:49 【问题描述】:

人们说async/await 只是为 promise 编写回调的另一种方式。但是,我觉得它们好像不可互换;事实上,回调在 Express 中会更好,因为它会立即将结果返回给用户。这是正确的吗?

在下面的示例中,假设我们不关心doSomethingAsync() 的结果,而是想立即重定向。在这里,我们使用await

router.get('/register', async (req, res) => 
    res.redirect('/')           
    await doSomethingAsync()
    console.log(1)


router.get('/', (req, res) => 
    console.log(2)
    ...

这将打印出1,然后是2,这意味着除非异步函数完成,否则我们将无法退出/register 处理程序并重定向。

在下面的版本中,我们在then 中使用带有回调的promise。

router.get('/register', (req, res) => 
    res.redirect('/')           
    doSomethingAsync().then(() => 
        console.log(1)
    )


router.get('/', (req, res) => 
   console.log(2)
   ...

这将打印出2,然后是1,这意味着我们可以立即退出并重定向用户。 第二种方式不是更好的性能吗?还是它们实际上是一样的?

【问题讨论】:

我很确定这两种方式都有相同的性能。但是如果你想确定,你可以使用 console.timer("myTimer") 然后使用 console.timeEnd("myTimer") 来设置它使用的时间。 【参考方案1】:

人们说async/await 只是为 promise 编写回调的另一种方式。但是,我觉得它们好像不能互换;

这是不正确的,它们确实可以互换。事实上,async/await 让您做事比使用简单的 Promise 更容易,因为 await 表达式可以无缝地插入到几乎任何控制流逻辑中,而使用简单的 Promise 则不能这样做,并且需要使用连续的.then() 调用来链接它们。

事实上,回调在 Express 中会更好,因为它会立即将结果返回给用户。这是正确的吗?

没有。回调是异步传递数据的不同机制;它不是“立即”,也不是明显更快,并且使用 Promise 编程的好处远远超过诉诸 callback hell 的任何可忽略的性能影响。另外,你的第二个例子不是真正的回调,它是一个承诺链。

这将打印出1,然后是2,这意味着除非异步函数完成,否则我们将无法退出/register 处理程序并重定向。

这是不正确的。 await 是非阻塞的。只要doSomethingAsync() 被调用,async function 就会返回给调用者,async function's 返回值是在调用console.log(1) 之后解析的promise。

这将打印出2,然后是1,这意味着我们可以立即退出并重定向用户。第二种方式不是更好的性能吗?还是它们实际上是一样的?

这两个 sn-ps 在算法上是相同的,并且由于 console.log(2) 依赖于客户端的浏览器执行由 res.redirect('/') 指示的 HTTP 请求,这与 doSomethingAsync() 无关,因此您实际上有一个竞争条件,并且既不能保证日志的顺序。它的性能也与使用await 的示例没有什么不同

【讨论】:

我认为在快速发展的 javascript 世界中,像这样的解释应该由试图替换功能 A 的功能 B 提供。否则人们只会认为功能 A 已经过时\坏\工作不同 感谢您的详细解释!为了确保,当你说它调用下面的指令并立即返回时,如果下面有一行使用 await 的结果会发生什么? ` router.get('/register', async (req, res) => res.redirect('/') var result = await doSomethingAsync(); console.log(1); console.log(result) `这里,你说console.log(1)会在promise解析之前被调用,但是console.log(result)也会被调用吗? “当你说它调用下面的指令时等待”——我没有这么说。我说它调用doSomethingAsync()。然后该函数立即返回,await 之后的语句直到doSomethingAsync() 返回的承诺被解决后才会被调用。

以上是关于Express 中的回调与等待性能的主要内容,如果未能解决你的问题,请参考以下文章

node.js 和 express:如何等待 udp 响应

等待异步函数完成而不添加回调

在 Express JS 和 NodeJS 中为 jsonp 回调函数添加参数

NodeJS Express 异步/等待

三Express 路由

在使用 express 呈现页面之前等待所有 mySql 请求完成