2017-09-15 1 views
0

Ich portiere ein altes Ruby-Skript, um Javascript zu verwenden, indem ich die Funktion als Cron-Instanz setze, damit es nach Plan läuft. Die Funktion fragt unsere MySQL-Datenbank ab, ruft Inventarinformationen für unsere Produkte ab und sendet dann Anfragen an einen Handelspartner, um unser Inventar auf der Site zu aktualisieren.NodeJS Loop-Problem aufgrund von Async-/Synchronicity-Problemen

Aufgrund der a-Synchronität der Knoten stoße ich auf Probleme. Wir müssen Anfragen in 1000 Artikel pro Anfrage teilen, und wir senden 10k Produkte. Das Problem ist, dass jede Anfrage nur die letzten 1000 Elemente jedes Mal sendet. Die for-Schleife, die sich innerhalb der while-Schleife befindet, bewegt sich vorwärts, bevor sie den json-Anfragetext fertiggestellt hat. Ich habe versucht, anon setTimeout-Funktionen in der while-Schleife zu versuchen und zu behandeln, sowie ein Objekt mit der Anfrage-Funktion und die Variablen zu übergeben und stopfen es in ein Array zu iterieren, sobald die While-Schleife abgeschlossen ist, aber ich bekomme das gleiche Ergebnis. Nicht sicher, was der beste Weg ist, damit umzugehen, damit jeder Antrag den korrekten Stapel der Einzelteile erhält. Ich muss auch 3 Minuten zwischen jeder Anforderung von 1000 Elementen warten, um die Anforderungsobergrenze nicht zu treffen.

query.on('end',()=>{ 
        connection.release(); 
        writeArray = itemArray.slice(0), 
        alteredArray = []; 
        var csv = json2csv({data: writeArray,fields:fields}), 
        timestamp = new Date(Date.now()); 
        timestamp = timestamp.getFullYear() + '-' +(timestamp.getMonth() + 1) + '-' + timestamp.getDate()+ ' '+timestamp.getHours() +':'+timestamp.getMinutes()+':'+timestamp.getSeconds(); 
        let fpath = './public/assets/archives/opalEdiInventory-'+timestamp+'.csv'; 

        while(itemArray.length > 0){ 
         alteredArray = itemArray.splice(0,999); 
         for(let i = 0; i < alteredArray.length; i++){ 
          jsonObjectArray.push({ 
           sku: alteredArray[i]['sku'], 
           quantity: alteredArray[i]["quantity"], 
           overstockquantity: alteredArray[i]["osInv"], 
           warehouse: warehouse, 
           isdiscontinued: alteredArray[i]["disc"], 
           backorderdate: alteredArray[i]["etd"], 
           backorderavailability: alteredArray[i]["boq"] 
          }); 
         } 

         var jsonObject = { 
          login: user, 
          password: password, 
          items: jsonObjectArray 
         }; 

         postOptions.url = endpoint; 
         postOptions.body = JSON.stringify(jsonObject); 
         funcArray.push({func:function(postOptions){request(postOptions,(err,res,body)=>{if(err){console.error(err);throw err;}console.log(body);})},vars:postOptions}); 
         jsonObjectArray.length = 0; 
        } 
        var mili = 180000; 
        for(let i = 0;i < funcArray.length; i++){ 
         setTimeout(()=>{ 
          var d = JSON.parse(funcArray[i]['vars'].body); 
          console.log(d); 
          console.log('request '+ i); 
          //funcArray[i]['func'](funcArray[i]['vars']); 
         }, mili * i); 
        } 
       }); 
      }); 
+0

Können Sie das auf einen [MCVE] reduzieren? (Sie können sogar das Problem auf dem Weg finden.) –

+0

danke für die Klarstellung, ich habe das Codebeispiel aktualisiert. –

Antwort

0

würden Sie müssen async/await oder Promise Asynchron-Aktionen in Knoten js zu behandeln. Ich bin mir nicht sicher, ob Sie eine Knotenversion haben, die Async unterstützt/erwarten, also habe ich eine vielversprechende Lösung ausprobiert.

query.on('end',() => { 
 
    connection.release(); 
 
    writeArray = itemArray.slice(0), 
 
     alteredArray = []; 
 
    var csv = json2csv({ data: writeArray, fields: fields }), 
 
     timestamp = new Date(Date.now()); 
 
    timestamp = timestamp.getFullYear() + '-' + (timestamp.getMonth() + 1) + '-' + timestamp.getDate() + ' ' + timestamp.getHours() + ':' + timestamp.getMinutes() + ':' + timestamp.getSeconds(); 
 
    let fpath = './public/assets/archives/opalEdiInventory-' + timestamp + '.csv'; 
 

 
    var calls = chunk(itemArray, 1000) 
 
         .map(function(chunk) { 
 
          var renameditemsArray = chunk.map((item) => new renamedItem(item, warehouse)); 
 
          var postOptions = {}; 
 
          postOptions.url = endpoint; 
 
          postOptions.body = JSON.stringify({ 
 
           login: user, 
 
           password: password, 
 
           items: renameditemsArray 
 
          }); 
 
          return postOptions; 
 
         }); 
 
    sequenceBatch(calls, makeRequest) 
 
     .then(function() { 
 
      console.log('done'); 
 
     }) 
 
     .catch(function(err) { 
 
      console.log('failed', err) 
 
     }); 
 

 
    function sequenceBatch (calls, cb) { 
 
     var sequence = Promise.resolve(); 
 
     var count = 1; 
 
     calls.forEach(function (callOptions) { 
 
      count++; 
 
      sequence = sequence.then(()=> { 
 
       return new Promise(function (resolve, reject){ 
 
        setTimeout(function() { 
 
         try { 
 
          cb(callOptions); 
 
          resolve(`callsequence${count} done`); 
 
         } 
 
         catch(err) { 
 
          reject(`callsequence ${count} failed`); 
 
         } 
 
        }, 180000); 
 
       }); 
 
      }) 
 
     }); 
 
     return sequence; 
 
    } 
 
    function makeRequest(postOptions) { 
 
     request(postOptions, (err, res, body) => { 
 
      if (err) { 
 
       console.error(err); 
 
       throw err; 
 
      } 
 
      console.log(body) 
 
     }); 
 
    } 
 

 
    function chunk(arr, len) { 
 
     var chunks = [], 
 
      i = 0, 
 
      n = arr.length; 
 
     while (i < n) { 
 
      chunks.push(arr.slice(i, i += len)); 
 
     } 
 
     return chunks; 
 
    } 
 

 
    function renamedItem(item, warehouse) { 
 
     this.sku = item['sku'] 
 
     this.quantity = item["quantity"] 
 
     this.overstockquantity = item["osInv"] 
 
     this.warehouse = warehouse 
 
     this.isdiscontinued = item["disc"] 
 
     this.backorderdate = item["etd"] 
 
     this.backorderavailability= item["boq"] 
 
    } 
 
});

Könnten Sie bitte diesen Schnipsel versuchen und lassen Sie mich wissen, ob es funktioniert? Ich kann es nicht testen konnte, da es im laufenden Betrieb aus. Die Kernlogik befindet sich in der sequenceBatch-Funktion. Die Antwort basiert auf einer anderen question, die erklärt, wie Timeouts und Versprechen zusammen arbeiten.

0

Es stellte sich heraus, dass dies keine Abschluss- oder asynchronen Probleme waren. Das Request-Objekt, das ich erstellte, verwendete Verweise auf Objekte anstelle von flachen Kopien, was dazu führte, dass die Daten mit dem gleichen Objekt ref im Ending-Array verknüpft wurden.

Verwandte Themen