【问题标题】:Using thunk to conditionally perform async does not execute twice使用 thunk 有条件地执行 async 不会执行两次
【发布时间】:2017-08-10 01:46:56
【问题描述】:

我正在关注Kyle Simpson Rethinking Asynchronous JavaScript 视频课程,我对他的 thunk 模式如何使用闭包感到困惑。代码是这样的:

function ajax(url, cb) {
  $.ajax({ url: `text/${url}`, type: 'GET', dataType: 'json' })
  .done(data => {
    cb(data)
  })
}

function getFile(file) {
  var text, fn;
  ajax(file,function(response){
    if (fn) {
      fn(response)
    } else {
      text = response
    }
  })
  return function th(cb) {
    if (text) {
      cb(text)
    } else {
      fn = cb
    }
  }
}

var th1 = getFile('1')
var th2 = getFile('2')
var th3 = getFile('3')

th1(function ready(text){
  console.log(text)
  th2(function ready(text){
    console.log(text)
    th3(function ready(text){
      console.log(text)
      th2(function (text) {
        console.log(text)
      })
    })
  })
})

我在最后的嵌套部分中添加了对th2 的额外调用。我希望这种闭包的使用能够返回最初从th2 打印的值,存储在getFile 函数中的闭包变量text 中,即不进行另一个网络调用。虽然这不是发生的情况:在t3 回调中打印文本后执行停止。

为什么这个闭包不返回它已经检索到的值?

【问题讨论】:

  • 那些笨蛋看起来像是穷人的承诺。我想知道他为什么放弃他已经拥有的 jQuery 承诺。
  • @Bergi 他没有使用 jquery。我把它扔在那里,这样我就可以快速验证网络面板中发生了什么。他最初有一个使用超时的fake_ajax 方法。
  • @bergi 他使用这些 thunk 作为谈论承诺的一部分。

标签: javascript callback closures thunk


【解决方案1】:

我希望使用闭包返回最初从th2 打印的值,存储在getFile 函数中的闭包变量text 中。虽然这不是发生的情况:在打印 t3 回调中的文本后执行停止。

这些 thunk 的问题是您不能使用它们两次(至少,当第一次使用是异步时)。该值永远不会存储在闭包变量text 中。为什么?因为th2是在ajax调用成功之前第一次运行,所以跑了

if (text) // still empty
  …
else // nope, nothing yet, store for later
 fn = cb

然后,当ajax调用回调时,它只会运行

if (fn) // we got something to call
  fn(response)
…

而不是text = response。所以当th2 被第二次调用(或者,更糟糕的是,立即从回调中)时,它会再次尝试将cb 存储在fn 变量中,但不会调用它。


一个可能的解决方法是这样做

… // in the thunk closure
ajax(file, function(response) {
  text = response;
  if (fn) {
    fn(response)
  }
})

相反,这将使您的代码工作,但仍然被破坏:如果在异步 ajax 回调之前多次调用 th2 会怎样?然后cb 覆盖之前的fn,所以最终我们需要维护一个回调数组,所有这些都应该被调用。好吧,这样做并为回调添加可链接性,并且已经 you've got the most basic Promise implementation

【讨论】:

  • 我不明白为什么回调中的text = response 不起作用。 因为 th2 在 ajax 调用成功之前第一次运行,它运行了fn=cb:为什么fn = cb 会第一次运行?
  • @1252748 因为还没有text,所以存储了函数。在ajax 成功之前,您是第一次调用返回的th 函数。 (请注意,如果获取文件 2 比获取文件 1 更快 - 呃,异步很难)
  • 这很难,但很明显你已经思考了很多。
猜你喜欢
  • 1970-01-01
  • 2023-01-26
  • 1970-01-01
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-08
相关资源
最近更新 更多