Javascript RxJS中的测序结果为;“内存不足”;错误
我需要处理一百万行记录,转换每一行,并将它们保存到多个文件中(按小时分类;每小时1个文件——我想用“过滤器”将它们拆分) 出于某种原因,我需要严格按顺序处理这些行。也就是说,如果第450000行的处理和保存时间更长(这是一个棘手的部分,因为fs与回调是异步的),那么处理不会跳到第450001行。。。它将等到45万完成。代码中的随机睡眠就是为了模拟那个场景 之前(使用simple Promise,无RxJs),我将创建N个承诺,每行一个,将它们保存在一个数组中,并通过reduce op进行链接,如下所述: 但我不想创造一百万个承诺的例子。因此,我研究了ReactiveX,希望它会像“推卸责任”;这意味着它不会等待,处理将在事件弹出时立即进行,并且处理所使用的资源(认为处理块基本上是幕后的承诺)将尽快释放 我尝试使用此代码验证:Javascript RxJS中的测序结果为;“内存不足”;错误,javascript,node.js,promise,rxjs,reactive-programming,Javascript,Node.js,Promise,Rxjs,Reactive Programming,我需要处理一百万行记录,转换每一行,并将它们保存到多个文件中(按小时分类;每小时1个文件——我想用“过滤器”将它们拆分) 出于某种原因,我需要严格按顺序处理这些行。也就是说,如果第450000行的处理和保存时间更长(这是一个棘手的部分,因为fs与回调是异步的),那么处理不会跳到第450001行。。。它将等到45万完成。代码中的随机睡眠就是为了模拟那个场景 之前(使用simple Promise,无RxJs),我将创建N个承诺,每行一个,将它们保存在一个数组中,并通过reduce op进行链接,如
import Rx from 'rxjs-es6/Rx';
import Q from 'q';
let subject = new Rx.Subject();
let processEventJsons = function(observable) {
observable.concatMap(eventJson => {
let deferred = Q.defer();
setTimeout(() => {
eventJson.procDatetime = new Date().toISOString();
deferred.resolve(eventJson);
}, Math.random() * 5000);
return Rx.Observable.fromPromise(deferred.promise)
})
.subscribe({
next: enrichedEventJson => {
console.log(JSON.stringify(enrichedEventJson));
},
error: err => console.error('something wrong occurred: ' + err),
complete: () => console.log('done'),
});
}
processEventJsons(
subject.filter(dataJson => dataJson.type === "interview").map(dataJson => {
return {event: "intv", datetime: dataJson.datetime}
})
)
processEventJsons(
subject.filter(dataJson => dataJson.type === "checkin").map(dataJson => {
return {event: "chki", datetime: dataJson.datetime}
})
)
for (let i = 0; i < 1000000; i++) {
if (Math.random() < 0.5) {
subject.next({id: i, type: "interview", datetime: new Date().toISOString()});
} else {
subject.next({id: i, type: "checkin", datetime: new Date().toISOString()});
}
}
subject.complete();
从“rxjs-es6/Rx”导入Rx;
从“Q”中导入Q;
让subject=new Rx.subject();
让processEventJsons=函数(可观察){
concatMap(eventJson=>{
设deferred=Q.deferred();
设置超时(()=>{
eventJson.procDatetime=新日期().toISOString();
deferred.resolve(eventJson);
},Math.random()*5000);
返回Rx.observed.fromPromise(延迟.承诺)
})
.订阅({
下一步:enrichedEventJson=>{
log(JSON.stringify(enrichedEventJson));
},
错误:err=>console.error('发生错误:'+err),
完成:()=>console.log('done'),
});
}
processEventJsons(
subject.filter(dataJson=>dataJson.type==“面试”).map(dataJson=>{
返回{event:“intv”,datetime:dataJson.datetime}
})
)
processEventJsons(
subject.filter(dataJson=>dataJson.type==“checkin”).map(dataJson=>{
返回{event:“chki”,datetime:dataJson.datetime}
})
)
对于(设i=0;i<1000000;i++){
if(Math.random()<0.5){
subject.next({id:i,键入:“面试”,datetime:newdate().toISOString()});
}否则{
subject.next({id:i,键入:“checkin”,datetime:newdate().toISOString()});
}
}
subject.complete();
但是。。。我一直得到:
致命错误:调用和重试上次分配失败-JavaScript堆内存不足
log(JSON.stringify(enrichedEventJson));直到“for循环”(在代码末尾)完成后才会打印
这让我觉得切换到RxJS并没有真正改善这种情况;它仍然在幕后等待承诺
还是我错误地使用了API?你能帮我指出哪里出了问题吗
更新:
假旗。我发现问题不在于RxJS的使用,而在于for循环(它太紧了)。所以我把它改成:
for (let i = 0; i < 1000000; i++) {
if (Math.random() < 0.5) {
setTimeout(() => {
subject.next({id: i, type: "interview", datetime: new Date().toISOString()});
});
} else {
setTimeout(() => {
subject.next({id: i, type: "checkin", datetime: new Date().toISOString()});
});
}
}
for(设i=0;i<1000000;i++){
if(Math.random()<0.5){
设置超时(()=>{
subject.next({id:i,键入:“面试”,datetime:newdate().toISOString()});
});
}否则{
设置超时(()=>{
subject.next({id:i,键入:“checkin”,datetime:newdate().toISOString()});
});
}
}
我将创建N个承诺,每行一个,将它们保存在一个数组中,并通过reduce op进行链接
这是一种简单但内存不足的方法。它使用了一百万个需要同时存在的承诺。相反,您可以使用递归方法在恒定内存中按顺序处理行:
function getInput(i) {
return {id: i, type: Math.random() < 0.5 ? "interview" : "checkin", datetime: new Date().toISOString()};
}
function process(eventJson) {
let deferred = Q.defer();
setTimeout(() => {
eventJson.procDatetime = new Date().toISOString();
deferred.resolve(eventJson);
}, Math.random() * 5000);
return deferred.promise;
}
function filteredProcess({type, datetime}) {
if (type === "interview")
return process({event: "intv", datetime});
if (type === "checkin")
return process({event: "chki", datetime});
}
function log(enrichedEventJson) {
console.log(JSON.stringify(enrichedEventJson));
}
function loop(i) {
if (i < 1000000)
return getInput(i)
.then(filteredProcess)
.then(log)
.then(() => loop(i+1));
else
return Q("done")
}
loop().then(console.log, err => console.error('something wrong occurred: ' + err));
函数getInput(i){
返回{id:i,type:Math.random()<0.5?“面试”:“签入”,datetime:new Date().toISOString()};
}
函数进程(eventJson){
设deferred=Q.deferred();
设置超时(()=>{
eventJson.procDatetime=新日期().toISOString();
deferred.resolve(eventJson);
},Math.random()*5000);
回报。承诺;
}
函数filteredProcess({type,datetime}){
如果(类型=“面试”)
返回进程({event:“intv”,datetime});
如果(类型=“签入”)
返回过程({事件:“chki”,datetime});
}
函数日志(enrichedEventJson){
log(JSON.stringify(enrichedEventJson));
}
函数循环(一){
如果(i<1000000)
返回getInput(i)
.然后(过滤过程)
.然后(日志)
.然后(()=>循环(i+1));
其他的
返回Q(“完成”)
}
loop().then(console.log,err=>console.error('发生了错误:'+err));
我将创建N个承诺,每行一个,将它们保存在一个数组中,并通过reduce op进行链接
这是一种简单但内存不足的方法。它使用了一百万个需要同时存在的承诺。相反,您可以使用递归方法在恒定内存中按顺序处理行:
function getInput(i) {
return {id: i, type: Math.random() < 0.5 ? "interview" : "checkin", datetime: new Date().toISOString()};
}
function process(eventJson) {
let deferred = Q.defer();
setTimeout(() => {
eventJson.procDatetime = new Date().toISOString();
deferred.resolve(eventJson);
}, Math.random() * 5000);
return deferred.promise;
}
function filteredProcess({type, datetime}) {
if (type === "interview")
return process({event: "intv", datetime});
if (type === "checkin")
return process({event: "chki", datetime});
}
function log(enrichedEventJson) {
console.log(JSON.stringify(enrichedEventJson));
}
function loop(i) {
if (i < 1000000)
return getInput(i)
.then(filteredProcess)
.then(log)
.then(() => loop(i+1));
else
return Q("done")
}
loop().then(console.log, err => console.error('something wrong occurred: ' + err));
函数getInput(i){
返回{id:i,type:Math.random()<0.5?“面试”:“签入”,datetime:new Date().toISOString()};
}
函数进程(eventJson){
设deferred=Q.deferred();
设置超时(()=>{
eventJson.procDatetime=新日期().toISOString();
deferred.resolve(eventJson);
},Math.random()*5000);
回报。承诺;
}
函数filteredProcess({type,datetime}){
如果(类型=“面试”)
返回进程({event:“intv”,datetime});
如果(类型=“签入”)
返回过程({事件:“chki”,datetime});
}
函数日志(enrichedEventJson){
log(JSON.stringify(enrichedEventJson));
}
函数循环(一){
如果(i<1000000)
返回getInput(i)
.然后(过滤过程)
.然后(日志)
.然后(()=>循环(i+1));
其他的
返回Q(“完成”)
}
loop().then(console.log,err=>console.error('发生了错误:'+err));