JavaScript:使用承诺调用递归函数

JavaScript:使用承诺调用递归函数,javascript,recursion,Javascript,Recursion,语言:JavaScript 递归-不是我最喜欢的话题 承诺——它们可能会让人困惑 递归+承诺-我需要在一个填充的房间里编程 我制作了这个JS提琴小游戏,我称之为喜剧,通过将问题简化为一些愚蠢的事情来保持我的理智。希望雅尔能从我的痛苦中得到笑声:) 问题: 每个递归调用都依赖于前一个调用的结果,但为了获得结果,我必须运行一个异步任务,并在其他子任务中使用该结果 这个“递归娱乐屋”帮我把问题归结到了这一点上——由于子任务仍在执行,原始的递归循环仍在以未定义的值继续进行。 有趣的房子-循环收集(-9

语言:JavaScript


递归-不是我最喜欢的话题

承诺——它们可能会让人困惑

递归+承诺-我需要在一个填充的房间里编程

我制作了这个JS提琴小游戏,我称之为喜剧,通过将问题简化为一些愚蠢的事情来保持我的理智。希望雅尔能从我的痛苦中得到笑声:)

问题:

每个递归调用都依赖于前一个调用的结果,但为了获得结果,我必须运行一个异步任务,并在其他子任务中使用该结果

这个“递归娱乐屋”帮我把问题归结到了这一点上——由于子任务仍在执行,原始的递归循环仍在以未定义的值继续进行。

有趣的房子-循环收集(-99)和99之间的随机数。一旦上一个数字和新数字之间的最后一个差值为正值,乐趣就结束了

打印“makeit here 1…makeit here 6”应该表明子任务处理正确,并且我们为下一个循环提供了一个值

当前它打印1,2,3,6,4,5:(

recursiveFunHouse.js

var recursiveFunHouse = function(num){
    console.log("Made it here 1");
    var newNum = performSideTasks();

    console.log("Made it here 6");
    console.log("newNum");
    console.log(newNum);
    if(newNum-num >0 ){
            recursiveFunHouse(newNum);
    }
    else{
        console.log("The FunHouse Generated These Numbers :")
      for(var i = 0; i <numList.length; i++){
         console.log(numList[i]);
      }
    }

};

var performSideTasks = function(){
    console.log("Made it here 2");
    someAsyncTask().then(function(num){
            anotherTask(num);
      console.log("made it here 5");
      return num;
        });


}

var someAsyncTask = function(){
  return new Promise (function(resolve, reject) {
    console.log("made it here 3");
    var randNum = Math.floor(Math.random()*99) + 1; 
    randNum *= Math.floor(Math.random()*2) == 1 ? 1 : -1;   

    setTimeout(function() { 
      numList.push(randNum)
      resolve(randNum)
    }, 100);
  });
}




var anotherTask = function(num){
  console.log("made it here 4");
    console.log(num);

};

var numList= [];

recursiveFunHouse(20);
var recursiveFunHouse=函数(num){
console.log(“在这里制作1”);
var newNum=performsdetasks();
console.log(“在这里制作6”);
console.log(“newNum”);
console.log(newNum);
如果(newNum>0){
recursiveFunHouse(纽纳姆);
}
否则{
log(“游乐场生成了这些数字:”)

对于注释中所述的(var i=0;i,您必须稍微修改
performsdetasks
,使其返回承诺:

var performSideTasks = function () 
{
  console.log( "Made it here 2" )
  return someAsyncTask().then( function ( num )
  {
    anotherTask(num);
    console.log("made it here 5")
    return num
  } )
} 
然后可以在主函数的
Then()
方法中使用异步结果

var recursiveFunHouse = function ( num )
{
  console.log( "Made it here 1" )
  performSideTasks().then( function ( newNum )
  {
    console.log( "Made it here 6" )
    console.log( "newNum" )
    console.log( newNum )
    if ( newNum-num > 0 )
    {
      recursiveFunHouse( newNum )
    }
    else
    {
      console.log( "The FunHouse Generated These Numbers :" )
      for( var i = 0 ; i <numList.length ; i++ )
      {
        console.log( numList[i] )
      }
    }
  } )
}
var recursiveFunHouse=函数(num)
{
console.log(“在这里创建1”)
performsdetasks().then(函数(newNum)
{
console.log(“在这里创建6”)
console.log(“newNum”)
console.log(newNum)
如果(newNum>0)
{
recursiveFunHouse(纽纳姆)
}
其他的
{
log(“游乐场生成了这些数字:”)

对于(var i=0;i,在经典的同步递归中,递归状态存储在从公共执行堆栈中推送和弹出的堆栈帧中。在异步递归中,递归状态可以存储在从公共承诺链头部推送和弹出的承诺对象中。例如:

函数asyncThing(asyncParam){//操作示例
const promiseDelay=(数据,毫秒)=>新承诺(res=>setTimeout(res,毫秒,数据));
返回promiseDelay(asyncParam,1000);//在1秒内用参数解析。
}
函数recFun(num){//示例“递归”异步函数
//执行recFun调用时执行的任何同步操作
//      ...
//并决定如何处理异步结果:递归还是完成?
函数决定(异步结果){
//根据需要在此处处理异步结果:
log(“asyncResult:+asyncResult”);
如果(asyncResult==0)
控制台日志(“点火”);
//检查是否需要进一步递归:
如果(异步结果<0)
返回“起飞”;//否,全部完成,返回非承诺结果
return recFun(num-1);//是的,再次调用recFun返回承诺
}
//返回通过执行异步操作并决定执行什么操作来解决的承诺。
//要明确的是,返回的承诺是从中返回的。然后调用
返回asyncThing(num),然后(decision);
}
//调用递归函数
乐趣(5)
.then(函数(结果){console.log(“完成,结果=”+result);})

.catch(函数(err){console.log(“oops:+err);});
performsdetask应该返回someAsynTask承诺本身,以便主函数可以在其中获取num值。然后()@Supersharp:我注意到你使用了与我见过的大多数代码不同的代码。这不一定是坏事,但要小心选择你的风格-因为在Javascript中,它可能会导致你意想不到的错误。全面、启发性的解释和示例!很好的解释。我会在Javascript中添加类似的代码,只要用“turn o”替换“thread”对于事件循环'@DeanRadcliffe',这是一个很好的观点。这是一个JavaScipt答案,但我使用了“线程”表示事件循环的调用不正确。答案已更新以消除混淆源。感谢您的评论。@traktor53谢谢,您的答案对我帮助很大。这是在客户端合并服务器端分页的完美代码,其中递归数取决于页数(下一页/下一页/下一页)。谢谢!