简体   繁体   English

使用thunk有条件地执行异步不会执行两次

[英]Using thunk to conditionally perform async does not execute twice

I'm following along with the Kyle Simpson Rethinking Asynchronous JavaScript video course and am confused about how his thunk pattern is using closures. 我跟着Kyle Simpson重新思考异步JavaScript视频课程,并对他的重击模式如何使用闭包感到困惑。 The code is like this: 代码是这样的:

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)
      })
    })
  })
})

I added the extra call to th2 in the final nested portion. 我在最后的嵌套部分中向th2添加了额外的调用。 I expected this use of closures to return the value originally printed from th2 , stored in the closure variable text in the getFile function, ie not make another network call. 我希望使用闭包可以返回最初从th2打印的值,该值存储在getFile函数的闭包变量text中,即不会进行另一个网络调用。 Though that is not what happens: execution stops after printing the text in the t3 callback. 尽管不会发生这种情况:在t3回调中打印文本后,执行停止。

Why doesn't this closure return its already retrieved value? 为什么此闭包不返回其已检索的值?

I expected this use of closures to return the value originally printed from th2 , stored in the closure variable text in the getFile function. 我期望使用闭包可以返回最初从th2打印的值,该值存储在getFile函数的闭包变量text中。 Though that is not what happens: execution stops after printing the text in the t3 callback. 尽管不会发生这种情况:在t3回调中打印文本后,执行停止。

The problem with these thunks is that you cannot use them twice (at least, when the first use is asynchronous). 这些重击的问题在于您不能使用它们两次(至少在第一次使用是异步的时候)。 The value is never stored in the closure variable text . 该值永远不会存储在闭包变量text Why? 为什么? Because th2 was run the first time before the ajax call succeeded, which ran 因为th2在ajax调用成功之前第一次运行,所以运行了

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

Then later, when ajax calls the callback, it will only run 然后,当ajax调用回调时,它将仅运行

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

and not text = response . 不是text = response So when th2 is called a second time later (or, worse, immediately from within the callback), it will again just try to store the cb in the fn variable, but nothing will call that. 因此,当第二次调用th2 (或更糟糕的是,立即从回调内部调用)时,它将再次尝试将cb存储在fn变量中,但是没有东西会调用它。


A possible workaround would be to do 一个可能的解决方法是

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

instead which would make your code work, but still be broken: what if th2 is called multiple times before the asynchronous ajax callback? 相反,这会使您的代码正常工作,但仍然会出错:如果在异步ajax回调之前多次调用th2怎么办? Then cb overwrites the previous fn , so ultimately we would need to maintain an array of callbacks that all should get called. 然后cb覆盖了之前的fn ,因此最终我们将需要维护一个回调数组,所有这些回调都应被调用。 Well, do that and add chainability for the callbacks, and you've got the most basic Promise implementation already. 好吧,这样做并为回调添加可链接性, 您已经拥有最基本的Promise实现

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM