2016-04-08 8 views
1

mongodbデータベースを解析し、APIから取得しているデータを追加しようとしています。特定の時間から今日までのすべてのユーザーのすべてのデータを取得したい。 私がやっていることは、毎回の繰り返しごとに5日間の各ユーザーデータを取得しているため、2〜3ヶ月分のデータが5日間に分かれていることです。NODE.JS:FATAL ERROR- JS割り当てが失敗しました - 大規模なjsonオブジェクトを解析中にメモリが不足しました

何らかの理由で、割り当てエラー - メモリ不足プロセスでこのエラーが発生しています。

特定のユーザーに到着したときにこのエラーが表示されるようですが、他のユーザーよりも多くのデータがあるようです。

スクリプトを実行するときにこのコマンドを試しました。node --max-old-space-size = 4028 worksnap.js。

var currentMonth = new Date(); 
    var startDate = new Date("February 1, 2016 00:00:00"); //Start from February 

var counter = 1; 
while (startDate.getMonth() <= currentMonth.getMonth()) { 
    //todo:: look if u have to increaze the start time, due the previous end time becomes start time it can take the same time time entries (have to be reviewd and make sure).... 
    var from = new Date(startDate).getTime()/1000; 
    startDate.setDate(startDate.getDate() + 5); 
    var to = new Date(startDate).getTime()/1000; 
    iterateThruAllStudents(from, to); 
} 

function getTimeEntriesFromWorksnap(error, response, body) { 
     //console.log(response.statusCode); 
     if (!error && response.statusCode == 200) { 
      parser.parseString(body, function (err, results) { 
       var json_string = JSON.stringify(results.time_entries); 
       var timeEntries = JSON.parse(json_string); 
       _.forEach(timeEntries, function (timeEntry) { 
        _.forEach(timeEntry, function (item) { 
         saveTimeEntry(item); 
        }); 
       }); 
      }); 
     } 
    } 

    function saveTimeEntry(item) { 
     Student.findOne({ 
       'worksnap.user.user_id': item.user_id[0] 
      }) 
      .populate('user') 
      .exec(function (err, student) { 
       if (err) { 
        throw err; 
       } 
       student.timeEntries.push(item); 
       student.save(function (err) { 
        if (err) { 
         console.log(err); 
        } else { 
         console.log('item inserted...'); 
        } 
       }); 

      }); 
    } 

    function iterateThruAllStudents(from, to) { 
     Student.find({status: 'student'}) 
      .populate('user') 
      .exec(function (err, students) { 
       if (err) { 
        throw err; 
       } 

       _.forEach(students, function (student, i) { 
        if (student.worksnap.user != null) { 
         setTimeout(function() { 
          var options = { 
           url: 'https://api.worksnaps.com/api/projects/' + project_id + '/time_entries.xml?user_ids=' + student.worksnap.user.user_id + '&from_timestamp=' + from + '&to_timestamp=' + to, 
           headers: { 
            'Authorization': 'Basic bGhNSVwJkVUFasSxx2loOFVyZkFyOENEZEsdxxxCdUlHdElWMHo0czo=' 
           } 
          }; 
          request(options, getTimeEntriesFromWorksnap); 
         }, 5000 * i); 
        } 
       }); 
      }); 
    } 

誰もがここで私が間違っているのかを知っている:

私のコードは次のようになりますか?

答えて

0

解決策が含まれていないため、これはコメントです。

一つの問題はである:

に見える二つのものがありますが、一人の学生のデータを処理するまで

while (startDate.getMonth() <= currentMonth.getMonth()) { 
    //todo:: look if u have to increaze the start time, due the previous end time becomes start time it can take the same time time entries (have to be reviewd and make sure).... 
    var from = new Date(startDate).getTime()/1000; 
    startDate.setDate(startDate.getDate() + 5); 
    var to = new Date(startDate).getTime()/1000; 
    iterateThruAllStudents(from, to); 
} 

あなたは待っていないが、あなたはのデータを要求しますすべての生徒が並行して

同様の問題はsetTimeoutです。実行時間に応じて、複数のリクエストのデータをメモリに保持する必要があるためです。

asyncroneループを解決するには、asyncまたはPromiseのようなものを使用する必要があります。

+0

また、stm中にsetTimeOut()を追加しようとしましたが、10-20秒間待つことになりましたが、そのどちらも失敗しました... –

+0

またsetTimeOut()function async? –

+1

@HisniFazlijaはい、 'setTimeout'を使って関数を呼び出すことは非同期です(私はそうではないと言っていませんでしたが、ここでは使用しないでください)。一定秒間待機する必要はありませんが、次のタスクを続行する前に1つのタスクが終了するまで待つ必要があります。そのため、[async](https://github.com/caolan/async)または[Promise/A +](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)を使用します。 )。これはまた、あなたがいつメモリを使い果たすかを判断するのにも役立ちます。 –

関連する問題