Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript RxJS中的测序结果为;“内存不足”;错误_Javascript_Node.js_Promise_Rxjs_Reactive Programming - Fatal编程技术网

Javascript RxJS中的测序结果为;“内存不足”;错误

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进行链接,如

我需要处理一百万行记录,转换每一行,并将它们保存到多个文件中(按小时分类;每小时1个文件——我想用“过滤器”将它们拆分)

出于某种原因,我需要严格按顺序处理这些行。也就是说,如果第450000行的处理和保存时间更长(这是一个棘手的部分,因为fs与回调是异步的),那么处理不会跳到第450001行。。。它将等到45万完成。代码中的随机睡眠就是为了模拟那个场景

之前(使用simple Promise,无RxJs),我将创建N个承诺,每行一个,将它们保存在一个数组中,并通过reduce op进行链接,如下所述:

但我不想创造一百万个承诺的例子。因此,我研究了ReactiveX,希望它会像“推卸责任”;这意味着它不会等待,处理将在事件弹出时立即进行,并且处理所使用的资源(认为处理块基本上是幕后的承诺)将尽快释放

我尝试使用此代码验证:

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));