将大量(>40,000)原生承诺链接在一起会消耗太多内存
Chaining a lot of (>40,000) native promises together eats up too much memory
我有一个项目,我需要编写一个函数来依次计算几件事,然后将结果写入SQL DB。不幸的是,我要重复4万多次。我使用node.js,并承诺可以实现这一点,但内存使用量几乎达到2GB,很多时候程序在进行10,000次左右的计算后就会停止运行。我开发了自己的原生promiseEach函数,它按顺序接受数组项,并将其与promise链接在一起。
我哪里做错了?:
function promiseEach(array,promiseFn){
return new Promise(function(resolve,reject){
try {
var promiseArray = [];
var json = { array: array, counter: 0 }
for (var i = 0; i < array.length; i++) {
promiseArray.push(promiseFn)
}
promiseArray.reduce(function(preFn,curFn,index,pArray){
return preFn
.then( function(z){ return json.array[json.counter++] })
.then(curFn)
},
Promise.resolve(json.array[json.counter]))
.then(resolve,reject)
}catch(err){
console.log("promiseEach ERROR:");
reject(err)
}
})
}
一开始你就把函数弄得太复杂了——据我所知,你对数组的每个内容都按顺序调用了promiseFn
下面的代码在功能上与你的代码
相同function promiseEach(array, promiseFn) {
return array.reduce(function(prev, item) {
return prev.then(function() {
return promiseFn(item);
});
}, Promise.resolve());
}
不能保证这将解决实际问题,尽管
的完整性,因为你是在nodejs编码,相同的代码写在ES2015+
let promiseEach = (array, promiseFn) =>
array.reduce((prev, item) =>
prev.then(() =>
promiseFn(item)
)
, Promise.resolve());
发布代码中的两行
.then( function(z){ return json.array[json.counter++] })
then(curFn)
似乎表明promseFn
将在前一个调用对其执行的操作完成后带一个新参数被调用,并且前一个调用的完成值不会在承诺链中使用。
为了避免在从每个函数返回之前创建(39,999左右)中间链式承诺,建议使用promiseFn
返回的中间承诺在它们被实现时调用承诺工厂函数,并返回一个仅由最后一个中间承诺实现的最终承诺。
下面的概念代码不包含对reduce
的调用,因为没有执行reduce操作:
function promiseEach( array, promiseFn) {
var resolve, reject;
var counter = 0;
var final = new Promise( function( r, j) { resolve = r; reject = j});
function nextPromise() {
promiseFn( array[counter++])
.then( (counter < array.length ? nextPromise : resolve), reject);
}
if( array.length) {
nextPromise();
}
else {
reject( new Error("promiseEach called on empty array"));
}
return final;
}
添加注释:
上面的promiseEach
函数在node/js中使用同步和异步promiseFn
进行测试,不并发更新数据数组。
- 同步测试
function promiseSynch( z) { return new Promise( function(resolve,reject){resolve(z);}); }
能够在大约10秒内处理一个包含100万个(1000000个)条目的数组,使用一台内存为1GB的Win7 i86笔记本,同时打开浏览器、编辑器和任务管理器。内存使用率稳定在可用内存的80%左右。
- 异步测试
function promiseAsynch( z) { var resolve; function delayResolve() { resolve( z); } return new Promise( ( r, j)=>{ resolve = r; setTimeout(delayResolve,1); }); }
在20分钟多一点的时间内,在同一个笔记本上管理了100,000个条目的数组,内存使用率也在80%左右。
结论测试表明承诺不会仅仅因为它们正在被使用而导致内存泄漏,并且它们应该能够处理将冗长的数组数据依次传递到承诺返回函数。
这意味着在完全解决问题之前,需要找到内存分配失败或神秘的处理中断的其他原因。作为一个建议,您可以从搜索与正在使用的DB库相关的内存泄漏问题开始。
- 有可能在来自链接的警报中有一个值吗
- mouseover和mouseleave文本颜色更改在指令链接中不起作用
- Webscratching自动化如何在没有链接TAG的情况下模拟点击HREF链接
- 如何在指令链接函数中使用从控制器传递的筛选器
- jquery animation.scrollTop()在mdl链接中不起作用
- 如何在不链接/jquery的情况下使用方法应用css属性数组
- 在npm链接后找不到命令
- 为什么jQuery只在某些链接中输入函数
- 如何在跟随链接之前显示(DOM)消息
- 悬停在非链接元素上时,使链接可见
- 如何在指令链接中定义的事件上测试$
- 在指令链接中访问 ngModel 的父对象
- 在传递链接时调用 javascript 函数
- 元素在调用链接函数时不在 DOM 中
- 何时应使用与号 实体 (&)不在 HTML 链接中使用
- Browserify - 在 package.json 中转换在符号链接模块中不起作用在 npm3 中
- 如何在编辑链接单击时首次加载页面时保留值
- 在脚本链接标记中使用注释
- 如何使用jquery在省略链接的同时查找文本
- 当鼠标悬停在导航链接上时,如何让导航链接进行动画处理