如何解决由.map函数

时间:2017-04-17 18:41:33

标签: node.js promise bluebird

我正在尝试使用node.js app将我的mssql数据库中的900万条记录导出到mysql数据库

我遇到了一个内存问题,我怀疑是由于我的地图功能。(Bluebird Promise.map)

下面的Myfucntion()调用doThis()函数,它从我的Mssql数据库中获取一组记录,然后将记录插入到MySql数据库中。

Myfucntion(){
Promise.map(ids, id => doThis(id).then(results => console.log(results)), { concurrency: 5});
}

const doThis = async (id) => {
  try{
       const results = await sql.query`select results where id = ${id}`;
        if((results && results.recordset) && results.recordset.length > 0 ) {
          results.recordset.map(asset =>  insertResultslAsset(convertResultAsset(asset)));
        }
  }
  catch(err){
      console.log(err)
  }
 };

convertResultAsset(asset)函数在执行插入之前创建一个4属性对象。

我怀疑发生内存泄漏是因为转换后的资产以.map迭代的形式逐步存储在内存中

我能够通过在程序上运行--max-old-space-size = 20000来缓解这个问题。

从doThis()函数执行插入后,我无需存储转换后的Assets。

有没有办法从.map函数中释放这些对象?

1 个答案:

答案 0 :(得分:1)

一个代码块中的asyncpromises太多了。另外,bluebird有内部错误处理程序挂钩,因此没有必要使用try-catch块(可能,此块可能会降低性能,请参阅此文章:optimization-killers

这是第一个简化版本:

const debug = require('debug')('my-app-name')

Myfucntion(){
    return Promise.map(
        ids,
        id => doThis(id),
        { concurrency: 5}
    )

}

function doThis(id) {
    const results = sql.query('select results where id = ${id}');
    if (
        results &&
        results.recordset &&
        results.recordset.length > 0
    ) {
        return results
            .recordset
            .map(asset => insertResultslAsset(convertResultAsset(asset)))
            .then(res => debug(res))
            .catch(err => debug('error', err);
    }
    return null
}

我删除了console.log,bcz我不确定它的异步/同步性质,debug模块可能在大多数情况下效果更好(但要查看其输出,您应该运行程序环境标志,如下所示:DEBUG=* nodejs app.js

我不确定100%问题是否已解决,因为还有两个未知函数:

  • insertResultslAsset
  • convertResultAsset

这些函数可能包含闭包和不必要的锁定变量吗?