2016-04-08 23 views
1

Bir API'den aldığım bazı verileri mongodb veritabanına ayırmaya ve eklemeye çalışıyorum. Her kullanıcı için tüm verileri bugüne kadar belirli bir zamandan almak istiyorum. Yani yaptığım şey, her kullanıcı verisi için her bir iterasyon için 5 gün boyunca geri dönüyorum, bu yüzden 2-3 aylık veri 5 güne ayrılıyor.NODE.JS: FATAL ERROR- JS Ayırma işlemi başarısız oldu - büyük json nesnelerini ayrıştırırken bellek ayırma işlemi gerçekleştiriliyor

Nedense bu hatayı Tahsis Edilemeyen Failer - İşlem dışı bellek ile alıyorum.

Bu hatayı, belirli bir kullanıcıya ulaştığım anda aldığım gibi görünüyor, cz diğerlerinden daha fazla veri alıyor gibi görünüyor.

Komutu çalıştırırken bu komutu denedim: node --max-old-space-size = 4028 worksnap.js.

Benim kod şöyle görünür:

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

Herkes bilir burada yanlış yapıyorum?

cevap

0

Bu, bir çözüm içermediğinden daha fazla bir yorumdur.

Bir problem ile:

balık görünüyor iki şey vardır tek öğrencinin verileri işlemek kadar

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

Bekleyemezsin yok, ama verilerini talep tüm öğrenciler paraleldir.

Benzer bir sorun setTimeout'dur, çünkü yürütme süresine bağlı olarak kodunuzun bellekte birden fazla isteğin verilerini tutması gerekir.

Asynchron döngülerini çözmek için async veya Promise gibi bir şey kullanmalısınız.

+0

Ayrıca stm sırasında 10-20 saniye beklemek için bir setTimeOut() eklemeyi denedim, ama bu da çalışmadı ... –

+0

da setTimeOut() işlevi async değil mi? –

+1

@HisniFazlija Evet, 'setTimeout' kullanarak bir işlevi çağırmak async'tir (ben demedim), ama söylediğim gibi burada kullanmamalısınız. Sabit bir süre beklemek istemezsiniz, ancak bir sonraki işinize devam etmeden önce bir görev bitene kadar beklemek istersiniz. Bunun için [async] (https://github.com/caolan/async) veya [Promise/A +] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise). Bu ayrıca, bellekten ne zaman çıkacağınızı belirlemenize de yardımcı olacaktır (eğer hala gerçekleşecekse). –

İlgili konular