节点递归承诺永远不会退出

Posted

技术标签:

【中文标题】节点递归承诺永远不会退出【英文标题】:Node recursive promise never exits 【发布时间】:2016-06-13 03:25:35 【问题描述】:

我有以下递归调用迭代器的递归函数

conversions.next() 调用是对 api 端点下一页的请求-承诺调用

conversions.done 只是检查是否没有更多页面

通过将调用作为第一个参数传递给 api 端点来启动此循环。

问题是我的节点进程永远不会使用这个退出,当 process._getActiveHandles() 在代码末尾运行时,我似乎有 10 + 打开的 TCP 套接字连接,但节点没有进一步的代码要执行,但不退出

const loadConversions = function loadConversions(httpCallPromise, allConversions) 
  allConversions = typeof allConversions !== 'undefined' ? allConversions : [];
  return httpCallPromise.then((conversions) => 
    allConversions = allConversions.concat(conversions.value);
    if (conversions.done === false) 
      return loadConversions(conversions.next(), allConversions);
    
    return Promise.resolve(allConversions);
  );
;


// this is the entry point for the code
if (args[0] === 'conversions') 
  loadConversions(queries.conversions())
  .then((allConversions) => 
    console.log(allConversions.length);
    return Promise.all(allConversions.map(db.insertConversion));
   )
   .then(() => 
     console.log('done db insertions');
     console.log(process._getActiveHandles().length);
   )
   .catch((err) => 
     console.log(err);
   );

process.getActiveHandles().length的输出是tcp socket类型的13个节点进程

这里是迭代器

const cakeRequest = function(options) 
// make the request
return rp(options)
.then((response) => 
  const processed = processResponse(response);
  return 
  next: function next() 
    const nextOptions = Object.assign(, options, 
      qs: Object.assign(, options.qs, 
        start_at_row: parseInt(options.qs.start_at_row, 10) + parseInt(options.qs.row_limit, 10),
      ),
    );
    return cakeRequest(nextOptions);
  ,
  value: processed.value,
  done: processed.done,
  row_count: processed.row_count,
  ;
)
.catch(handleError);
;

【问题讨论】:

请向我们展示您对该迭代器的实现以及您对loadConversions 的初始调用。看起来done 将永远留在false 我添加了迭代器实现和初始调用。奇怪的是,console.log('done db inserts') 运行,尽管它后面没有代码,但进程永远不会退出 很有可能它与实际的递归承诺部分无关,因为它确实执行了后面的代码,但我不知道还有什么可以让节点进程保持打开状态。 是的,如果记录了“done db insertions”,那么您的递归已经成功。 db 是什么东西,需要明确关闭吗? insertConversion 是否需要 this 上下文? 【参考方案1】:

我的问题似乎与用于数据库插入的 knex 库有关。如果池从未关闭,则该进程永远不会退出。这对我来说似乎很奇怪,但最后调用 knex.destroy 让进程退出

【讨论】:

以上是关于节点递归承诺永远不会退出的主要内容,如果未能解决你的问题,请参考以下文章

节点无错误退出且不等待承诺(事件回调)

在递归节点函数中从 Mongoose 检索树数据

使用承诺和递归迭代文件目录

如何做出递归承诺

函数递归

在 node.js 中承诺一个递归函数