node.js表搜索失败,并且正在使用promise [英] node.js table search fails with promises in use

查看:261
本文介绍了node.js表搜索失败,并且正在使用promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要在这里学习东西。我喜欢学习!感谢您提供任何帮助!

I'm going to learn something here. I love to learn! Thanks in advance for any help!

这里有30行的Node.js JavaScript。这是一个标准的表搜索。为了简单起见,我的表是16个整数,0到15的序列。函数compareRow报告猜测的行 是否具有低于,等于或高于对应于事务 t ; t 需要行号 r = t 。 (当然,更长的代码更复杂。)我已经删除了所有我可以为你解散的东西。

Here's 30 lines of Node.js JavaScript. It's a standard table search. For simplicity, my "table" is a sequence of 16 integers, 0 to 15. Function compareRow reports whether a guessed row r has a row number below, equal, or above a row corresponding to a transaction t; t needs row number r = t. (Sure, the longer code is more complex.) I've removed everything I could to de-clutter for you.

异步问题问题)鼓励我使用承诺。我的更长的代码需要 bluebird ,并获得相同的结果。此代码使用JavaScript Promises。

Asynchronous issues (and some of you here in past questions) have encouraged me to use Promises. My longer code requires bluebird and gets identical results. This code uses JavaScript Promises.

'use strict'
function compareRow(r, t, low, high) {
  return new Promise(function(resolve, reject) {
    console.log('compareRow   r=' + r + '   t=' + t + '   low=' + low +
        '   high=', high)
    return resolve(r - t)
  })
}
function findRow(t) {
  let lo = 0, hi = 15, mid
  return new Promise(function(resolve, reject) {
    let mustBreak = false
    let count = 0, maxCount = 3
    do {
      mid = Math.floor((lo + hi) / 2)
      compareRow(mid, t, lo, hi)
      .then(function(ans, error) {
        console.log('findRow got compareRow(' + mid + ')=' + ans)
        if (error) { mustBreak = true; return reject(error) }
        else if (ans === 0) { mustBreak = true; return resolve(mid) }
        else if (ans < 0) lo = mid
        else if (ans > 0) hi = mid
      })
    } while (!mustBreak && ++count < maxCount)
  })
}
findRow(2)
.then(function(ans1, err1) {
  console.log('for findRow(2):   ans=' + ans1 + '   err=' + err1)
})

批评:


  • 使用变量 mustBreak 是icky。在每个地方我都使用了mustbreak = true ,我宁愿选择 break return resolve(n) / li>
  • 我认识到,在回调函数中,JavaScript将我的promise返回(例如,返回解析(1))视为来自回调函数的返回,而不是promise函数在函数的顶部。因此,在每次这样的调用时,JavaScript跟踪两个执行链:一个用于解析拒绝,一个用于回调后列出的代码。 Ick。第二个是非预期的执行链。

  • JSHint不喜欢涉及 ans 的回调函数。它正确地识别在 循环中的函数。 Ick,除了在JSHint中这个好的建议可能不是最好的帐户回调函数。

  • The use of variable mustBreak is icky. At each place I've used mustBreak=true, I'd rather both break and return resolve(n) (or whatever).
  • I recognize that within the callback functions, JavaScript treats my promise returns (return resolve(1), for example) as returns from the callback functions, not from the promise functions at the top of the function. Hence, at each such call, JavaScript tracks two chains of execution: one for the resolve or reject and one for code listed after the callback. Ick. That second one is an unintended chain of execution.
  • JSHint doesn't like the callback function involving ans. It correctly recognizes the function to be inside the for loop. Ick, except that this good advice in JSHint may not best account for callback functions.

基于console.log消息, ,执行就像我想通过第17行( compareRow(mid,t,lo,hi))。我期望console.log会显示我:

Based on console.log messages I have since removed, execution runs as I wanted through line 17 (compareRow(mid, t, lo, hi)). I expected console.log would show me something like:

compareRow   r=7   t=2   low=0   high= 15
findRow got compareRow(7)=5
compareRow   r=3   t=2   low=0   high= 7
findRow got compareRow(3)=1
compareRow   r=1   t=2   low=0   high= 3
findRow got compareRow(1)=-1
compareRow   r=1   t=2   low=1   high= 3
findRow got compareRow(3)=1
compareRow   r=2   t=2   low=1   high= 3
findRow got compareRow(3)=0
for findRow(2):   ans=2   err=undefined

而是:

compareRow   r=7   t=2   low=0   high= 15
compareRow   r=7   t=2   low=0   high= 15
compareRow   r=7   t=2   low=0   high= 15
findRow got compareRow(7)=5
findRow got compareRow(7)=5
findRow got compareRow(7)=5

出现


  • 执行进入 compareRow

  • 或者至少,该循环将是无限循环,除非是循环,否则循环将是无限循环。

  • 由于循环停止,回调处理答案似乎并不意外( findRow has compareRow(7)= 5 ),并且调用循环运行的次数(三次)。

  • 在回调代码运行时,处理输出的代码不再侦听。

  • Execution gets into compareRow (possibly in a timely way), but doesn't get on time into the callback function that receives that answer, resulting in an infinite loop.
  • Or at least, that loop would be infinite except for the loop counter that limits the loop to three cycles.
  • Given that the loop stops, it appears no accident that callback processes the answers (findRow got compareRow(7)=5) and gets called the same number of times the loop ran (three times).
  • By the time that callback code runs, the code to process the output is no longer listening.

问题:


  • 有没有办法,我可以鼓励JavaScript调度程序来处理我的代码?

  • Is there a way I can encourage the JavaScript scheduler to process the code as I intend? (This seems an entirely standard use case for Promises!)

如何更好地写这段代码?

How can I write this code better?

编辑:措辞和问题变更;所有的效果与原始帖子相同。删除了很多行代码。更正了语法错误。

Wording and question changes; all to the same effect as the original post. Deleted many lines of code. Corrected a syntax error.

推荐答案

@Bergi:如果你关心Stack Overflow中的分数,请在一个答案中发布一些措辞,我会让你的接受的解决方案。

@Bergi: Well done indeed! If you care about points in Stack Overflow, please post some wording in an answer and I'll make yours the accepted solution.

我说,一开始我会学习这里的东西。我确实。下面是一个反模式,因为JavaScript不会中断循环为你在其正文内部创建的promise。你不能在异步代码中使用这样的循环。

I said at the start I'd learn something here. I did, indeed. The following is an anti-pattern because JavaScript doesn't interrupt the loops "for the promises you create inside its body. You cannot use such loops in asynchronous code."

NOTE: Don't do this at home!
do {
  callPromiseFunction()
  .then(function(results, error) {
    // do something with results
  })
} while (/*some condition*/)

替代方法:使用递归方法,下一步从异步promise回调。

The alternative: "Use a recursive approach instead, wherein you can call the next step from an asynchronous promise callback."

我也学到了以下工作。我不知道它是要模拟,但它证明是足够的这个代码。

I also learned that the following works. I don't know that it's to be emulated, but it proved sufficient on this code.

NOTE: This was sufficient in this code to start the promise chain.
return new Promise
.all([callNonrecursivePromiseFunc(1), callNonrecursivePromiseFunc(2)]
.then(function(result, error) {
  callRecursivePromiseFunction(result)
  .then(function(results, error) {
    // do something with results
  })
})

这里是我使用Bergi的建议来改变我的代码,它的工作原理,最后,再次,我已经删除了大量的错误检查,以减少大量。 >

Here's how I used Bergi's advice to change my code. It works. Finally. Whew! Again, I've removed lots of error checking and such to reduce the bulk.

'use strict'
let Promise = require('bluebird')
function compareRow(t, r, low, high) {
  return new Promise(function(resolve, reject) {
    console.log('compareRow   t=' + t + '   r=' + r + '   low=' + low +
        '   high=', high)
    let recursion = (r === null)  // distraction; skip it
    if (recursion) {
      r = Math.floor((low + high) / 2)
      if (r < t) low = r
      else if (r > t) high = r
      else if (r === t) return resolve(r)
      compareRow(t, null, low, high)  // recursion; this is the point
      .then(function(result, error) {
        return resolve(result)
      })
    } else {
      return resolve(r - t)  // distraction; skip it
    }
  })
}
function findRow(t) {
  return new Promise(function(resolve, reject) {
    let lo = 0, hi = 15
    console.log('findRow   t=' + t + '   lo=' + lo + '   hi=' + hi)
    return new Promise
    .all([compareRow(t, lo, lo, hi), compareRow(t, hi, lo, hi)])
    .then(function(result, error) {
      let ans = result[0]
      console.log('findRow got compareRow(' + lo + ')=' + ans)
      if (ans === 0) return resolve(lo)
      ans = result[1]
      console.log('findRow got compareRow(' + hi + ')=' + ans)
      if (ans === 0) return resolve(hi)
      compareRow(t, null, lo, hi)  // this is a recursive call
      .then(function(result, error) {
        return resolve(result)
      })
    })
  })
}
findRow(2)
.then(function(ans1, err1) {
  console.log('for findRow(2):   ans=' + ans1 + '   err=' + err1)
})

注释:


  • 请注意使用bluebird Promises。

  • 使用递归方法:


    • 需要变量 mustBreak 走了。这是一个Ick。

    • 每次我调用resolve或reject时,我的声明范围相同。这是一个Ick。

    • 在任何时候我都不能在循环中定义一个函数。 JSHint更快乐。这是一个Ick。

    • Please note the use of bluebird Promises. This code fails with JavaScript Promises.
    • With the recursive approach:
      • The need for variable mustBreak went away. That was an "Ick".
      • Each time I call "resolve" or "reject", I'm in the same scope as the declarations. That was an "Ick".
      • At no point do I define a function within a loop. JSHint is happier. That was an "Ick".

      这篇关于node.js表搜索失败,并且正在使用promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆