我有一个项目,我需要编写一个函数来按顺序计算几个东西,然后将结果写入SQL DB。不幸的是,我需要重复这个超过40,000次。 我使用node.js并承诺完成此任务,但是在10,000次左右的计算之后程序刚刚死亡的内存使用量几乎达到2GB。我开发了自己的本机promiseEach函数,该函数以数量方式获取数组项并将其与promises链接。
我在这里做错了什么?:
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)
}
})
}
答案 0 :(得分:6)
好吧,你开始过度复杂的功能 - 从我所知道的,你按顺序为每个数组内容调用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());
答案 1 :(得分:3)
发布代码中的两行
.then( function(z){ return json.array[json.counter++] })
then(curFn)
似乎表示promseFn
将在前一次调用完成的操作完成后使用新参数调用,并且前一次调用的已实现值未在promise链中使用。
在从每个函数返回之前避免创建(39,999左右)中间链式promise的建议是使用promiseFn
返回的中间promise来在它们满足时调用promise工厂函数,并返回final承诺只有最后的中间承诺才能实现。
后面的概念代码不包含对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万(1000,000)条目的数组。内存使用量持平至可用内存的80%左右。
异步测试
function promiseAsynch( z) {
var resolve;
function delayResolve() {
resolve( z);
}
return new Promise( ( r, j)=>{
resolve = r;
setTimeout(delayResolve,1);
});
}
在同一台笔记本电脑上管理了超过20分钟的100,000个条目,同样平板电脑的使用率约为80%。
<强>结论强>
测试表明,Promise不会因为它们被使用而导致内存泄漏,并且它们应该能够处理将冗长的数组数据顺序传递到promise返回函数中。
这意味着存在内存分配失败或神秘处理中断的其他一些原因,需要在问题完全解决之前找到。作为建议,您可以从搜索与正在使用的DB库相关的内存泄漏问题开始。