Javascript node.js表搜索失败,承诺正在使用
我将在这里学到一些东西。我喜欢学习!提前感谢您的帮助 这里有30行Node.js JavaScript。这是一个标准的表格搜索。为了简单起见,我的“表”是一个16个整数的序列,从0到15。函数compareRow报告猜测的行r的行号是否低于、等于或高于对应于事务t的行;t需要行号r=t。(当然,代码越长就越复杂。)我已经删除了所有可以为您消除混乱的内容 异步问题(以及你们中的一些人在过去的问题中)鼓励我使用承诺。我的较长代码需要bluebird,并得到相同的结果。此代码使用JavaScript承诺Javascript node.js表搜索失败,承诺正在使用,javascript,node.js,callback,bluebird,es6-promise,Javascript,Node.js,Callback,Bluebird,Es6 Promise,我将在这里学到一些东西。我喜欢学习!提前感谢您的帮助 这里有30行Node.js JavaScript。这是一个标准的表格搜索。为了简单起见,我的“表”是一个16个整数的序列,从0到15。函数compareRow报告猜测的行r的行号是否低于、等于或高于对应于事务t的行;t需要行号r=t。(当然,代码越长就越复杂。)我已经删除了所有可以为您消除混乱的内容 异步问题(以及你们中的一些人在过去的问题中)鼓励我使用承诺。我的较长代码需要bluebird,并得到相同的结果。此代码使用JavaScript承
'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)
})
相反,我得到了:
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 get compareRow(7)=5)并以循环运行的相同次数(三次)被调用似乎不是偶然的
- 当回调代码运行时,处理输出的代码不再侦听
- 是否有一种方法可以鼓励JavaScript调度器按照我的意愿处理代码?(这似乎是承诺的完全标准用例!)
- 如何才能更好地编写此代码
编辑:措辞和问题变更;所有这些都与原始帖子具有相同的效果。删除了许多行代码。更正了一个语法错误。@Bergi:做得好!如果你关心堆栈溢出中的点,请在回答中发布一些措辞,我会让你的成为公认的解决方案 我一开始说我会在这里学到一些东西。确实是这样。以下是一种反模式,因为JavaScript不会“为在其主体内创建的承诺”中断循环。不能在异步代码中使用此类循环 另一种方法是:“使用递归方法,您可以从异步承诺回调调用下一步。” 我还了解到,下面的工作。我不知道它是否可以被仿真,但在这段代码中已经证明了这一点
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的建议来更改代码的。它起作用了。最后唷!同样,我已经删除了大量的错误检查等,以减少批量
'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)
})
“严格使用”
让承诺=要求(‘蓝鸟’)
功能比较器低(t、r、低、高){
返回新承诺(功能(解决、拒绝){
log('compareRow t='+t+'r='+r+'low='+low+
‘高=’,高)
让递归=(r==null)//分散注意力;跳过它
if(递归){
r=数学楼层((低+高)/2)
如果(rt)高=r
else if(r==t)返回resolve(r)
compareRow(t,null,low,high)//递归;这就是重点
.then(函数(结果、错误){
返回解析(结果)
})
}否则{
返回resolve(r-t)//分心;跳过它
}
})
}
函数findRow(t){
返回新承诺(功能(解决、拒绝){
设lo=0,hi=15
log('findRow t='+t+'lo='+lo+'hi='+hi)
回报新的承诺
.all([compareRow(t,lo,lo,hi),compareRow(t,hi,lo,hi)])
.then(函数(结果、错误){
设ans=结果[0]
log('findRow获得了compareRow('+lo+')='+ans)
如果(ans==0)返回解析(lo)
ans=结果[1]
log('findRow获得了compareRow('+hi+')='+ans)
如果(ans==0)返回解析(hi)
compareRow(t,null,lo,hi)//这是一个递归调用
.then(函数(结果、错误){
返回解析(结果)
})
})
})
}
芬德罗(2)
.then(函数(ans1,err1){
log('for findRow(2):ans='+ans1+'err='+err1)
})
评论:
- 请注意使用蓝鸟承诺。这段代码因JavaScript承诺而失败
- 使用递归方法:
- 对变量mustBreak的需求消失了。那是一个“嘀嗒”
- 每次我调用“resolve”或“reject”,我都与声明处于同一范围内。那是一个“嘀嗒”
- 在任何时候我都不能在循环中定义函数。杰希特更快乐。那是一个“嘀嗒”
- 这段代码有一些不受欢迎的复杂性,因为我使用compareRow用于递归和非递归目的。哎呀。我在这里不够优雅
伯吉:干得好!如果你关心堆栈溢出中的点,请在回答中发布一些措辞,我会让你的成为公认的解决方案 我一开始说我会在这里学到一些东西。确实是这样。以下是一种反模式,因为JavaScript不会“为在其主体内创建的承诺”中断循环。不能在异步代码中使用此类循环 另一种方法是:“使用递归方法,您可以从异步承诺回调调用下一步。” 我还了解到,下面的工作。我不知道它是否可以被仿真,但在这段代码中已经证明了这一点
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的建议来更改代码的。它起作用了。最后唷!同样,我已经删除了大量的错误检查等,以减少批量
'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)
})
“严格使用”
让承诺=要求(‘蓝鸟’)
功能比较器低(t、r、低、高){
返回新承诺(功能(解决、拒绝){
log('compareRow t='+t+'r='+r+'low='+low+
‘高=’,高)
让递归=(r==null)//分散注意力;跳过它
if(递归){
r=数学楼层((低+高)/2)
如果(rt)高=r
else if(r==t)返回resolve(r)
compareRow(t,null,low,high)//重复