2016-08-02 11 views
0

Hallo Leute ich Async NPM package und eachLimit function in Meteor verwenden möchten 1.3+ Ich benutzte es später ohne Meteor wie unten und es gut funktioniert:mit Async in Meteor 1.3+

var items = ["test", "test2","test3","test4","test5","test6","test7","test8","test9","test10","test11","test12","test13","test14","test15","test16","test17","test18","test19","test20"]; 
async.eachLimit(items, 5, (item, callback) => { 
         try { 
          //console.log(item); 
          heavyProcess(item); 
         } 
         catch (e) { 
          return callback(e); 
         } 
         callback(); 
        }, (err) => { 
         if (err) console.error(err.message); 
        }); 
function heavyProcess(item) { 
setTimeout(function() { 
      console.log(item); 
     }, Math.floor(Math.random() * 10000)); 
} 

du hier sehen können: https://jsfiddle.net/g0L90f3h/

Dies ist vor Code-Ausgang:

test3 
test8 
test18 
test5 
test20 
test15 
test19 
test 
test9 
test11 
test14 
test17 
test2 
test12 
test4 
test10 
test13 
test7 
test16 
test6 

Above Ausgang vollkommen korrekt ist. Nun wandern ich oben Code Meteor wie unten:

// startup.js 
import async from 'async'; 
let items = ["test", "test2","test3","test4","test5","test6","test7","test8","test9","test10","test11","test12","test13","test14","test15","test16","test17","test18","test19","test20"]; 
      async.eachLimit(items, 5, (item, callback) => { 
       try { 
        my_utils.heavyProcessSimulator(item); 
       } 
       catch (e) { 
        return callback(e); 
       } 
       callback(); 
      }, (err) => { 
       if (err) console.error(err.message); 
      }); 

// my_utils.js 
    heavyProcessSimulator(item) { 
     Meteor._sleepForMs(Math.floor(Math.random() * 10000)); 
     console.log(item); 
    } 

Aber es ist Rückkehr unter Ausgabe, die falsch ist:

I20160802-18:25:07.959(4.5)? test 
I20160802-18:25:15.477(4.5)? test2 
I20160802-18:25:20.915(4.5)? test3 
I20160802-18:25:28.284(4.5)? test4 
I20160802-18:25:31.842(4.5)? test5 
I20160802-18:25:35.694(4.5)? test6 
I20160802-18:25:38.871(4.5)? test7 
I20160802-18:25:48.812(4.5)? test8 
I20160802-18:25:52.452(4.5)? test9 
I20160802-18:25:58.944(4.5)? test10 
I20160802-18:26:06.411(4.5)? test11 
I20160802-18:26:08.461(4.5)? test12 
I20160802-18:26:09.135(4.5)? test13 
I20160802-18:26:17.474(4.5)? test14 
I20160802-18:26:24.613(4.5)? test15 
I20160802-18:26:31.605(4.5)? test16 
I20160802-18:26:34.022(4.5)? test17 
I20160802-18:26:36.792(4.5)? test18 
I20160802-18:26:39.646(4.5)? test19 
I20160802-18:26:41.706(4.5)? test20 

Warum dies geschieht und wie diese zu beheben? Ich teste viele Dinge, finde aber kein Problem. Warum wird die Synchronisierung ausgeführt?

Edit:


Vielen Dank für @hwillson für umfangreiche Antworten ich den Code ändern, wie unten, aber immer noch Ausgang ist falsch. Das ist mein neuer Code:

import async from 'async'; 
const items = ["test", "test2", "test3", "test4", "test5", "test6", "test7", "test8", "test9", "test10", "test11", "test12", "test13", "test14", "test15", "test16", "test17", "test18", "test19", "test20"]; 

     async function heavyProcessSimulator(item) { 
      console.log("Process Start for: " + item); 
      Meteor._sleepForMs(Math.floor(Math.random() * 10000)); 
      console.log("Process Finished for: " + item); 
     } 

     async.eachLimit(items, 5, (item, callback) => { 
      try { 
       heavyProcessSimulator(item); 
      } catch (e) { 
       return callback(e); 
      } 
      callback(); 
     }, (err) => { 
      if (err) console.error(err.message); 
     }); 

Und das ist Ausgabe:

I20160805-13:45:00.014(4.5)? Process Start for: test 
I20160805-13:45:00.014(4.5)? Process Start for: test2 
I20160805-13:45:00.015(4.5)? Process Start for: test3 
I20160805-13:45:00.015(4.5)? Process Start for: test4 
I20160805-13:45:00.016(4.5)? Process Start for: test5 
I20160805-13:45:00.016(4.5)? Process Start for: test6 
I20160805-13:45:00.017(4.5)? Process Start for: test7 
I20160805-13:45:00.017(4.5)? Process Start for: test8 
I20160805-13:45:00.018(4.5)? Process Start for: test9 
I20160805-13:45:00.023(4.5)? Process Start for: test10 
I20160805-13:45:00.024(4.5)? Process Start for: test11 
I20160805-13:45:00.024(4.5)? Process Start for: test12 
I20160805-13:45:00.025(4.5)? Process Start for: test13 
I20160805-13:45:00.025(4.5)? Process Start for: test14 
I20160805-13:45:00.026(4.5)? Process Start for: test15 
I20160805-13:45:00.026(4.5)? Process Start for: test16 
I20160805-13:45:00.027(4.5)? Process Start for: test17 
I20160805-13:45:00.027(4.5)? Process Start for: test18 
I20160805-13:45:00.028(4.5)? Process Start for: test19 
I20160805-13:45:00.029(4.5)? Process Start for: test20 
I20160805-13:45:00.665(4.5)? Process Finished for: test19 
I20160805-13:45:00.744(4.5)? Process Finished for: test2 
I20160805-13:45:00.841(4.5)? Process Finished for: test 
I20160805-13:45:00.917(4.5)? Process Finished for: test11 
I20160805-13:45:02.438(4.5)? Process Finished for: test4 
I20160805-13:45:02.953(4.5)? Process Finished for: test5 
I20160805-13:45:04.727(4.5)? Process Finished for: test3 
I20160805-13:45:05.510(4.5)? Process Finished for: test8 
I20160805-13:45:05.562(4.5)? Process Finished for: test7 
I20160805-13:45:05.849(4.5)? Process Finished for: test16 
I20160805-13:45:06.231(4.5)? Process Finished for: test17 
I20160805-13:45:06.527(4.5)? Process Finished for: test12 
I20160805-13:45:06.959(4.5)? Process Finished for: test18 
I20160805-13:45:07.147(4.5)? Process Finished for: test10 
I20160805-13:45:07.313(4.5)? Process Finished for: test13 
I20160805-13:45:08.027(4.5)? Process Finished for: test6 
I20160805-13:45:08.736(4.5)? Process Finished for: test15 
I20160805-13:45:08.912(4.5)? Process Finished for: test9 
I20160805-13:45:08.962(4.5)? Process Finished for: test20 
I20160805-13:45:08.975(4.5)? Process Finished for: test14 

Wie Sie async jetzt über Codes zu sehen, aber immer noch limit nicht korrekt. Es ruft alle 20 Elemente zuerst auf und verarbeitet sie dann.

+1

Das liegt daran, dass 'Meteor._sleepForMs' blockiert, während' setTimeout' ist nicht Blockierung. Überprüfen Sie dies: https://github.com/nodejs/node/blob/master/doc/topics/blocking-vs-non-blocking.md –

+0

Vielen Dank für Ihre Aufmerksamkeit. Aber ich benutze 'eachLimit' um diese Schleife asynchron zu machen. – b24

+0

Ich denke, wenn wir 'async.eachLimit' verwenden, ist es nicht wichtig zwischen' timeout' oder 'Meteor._sleepForMs', weil es asynchron ist und es als async funktionieren würde. Ist es richtig? – b24

Antwort

1

Meteor 1.3+ hat in async/await Unterstützung (auf dem Client und Server), dank der Meteor ecmascript Paket eingebaut. Sie müssen kein Drittanbieterpaket verwenden, um den Code asynchron auszuführen. Zum Beispiel:

Beispiel Server: /server/main.js

import { Meteor } from 'meteor/meteor'; 

const items = [ 
    "test", "test2", "test3", "test4", "test5", "test6", "test7", "test8", 
    "test9", "test10", "test11", "test12", "test13", "test14", "test15", 
    "test16", "test17", "test18", "test19", "test20" 
]; 

async function heavyProcessSimulator(item) { 
    Meteor._sleepForMs(Math.floor(Math.random() * 10000)); 
    console.log(item); 
} 

items.forEach((item) => { 
    heavyProcessSimulator(item); 
}); 

Beispielausgabe:

I20160802-15:15:47.220(-4)? test16 
I20160802-15:15:47.959(-4)? test9 
I20160802-15:15:48.331(-4)? test18 
I20160802-15:15:49.183(-4)? test7 
I20160802-15:15:49.211(-4)? test13 
I20160802-15:15:49.289(-4)? test14 
I20160802-15:15:49.587(-4)? test 
I20160802-15:15:49.776(-4)? test17 
I20160802-15:15:51.195(-4)? test15 
... 

Client-Beispiel: /client/main.js

const items = [ 
    "test", "test2", "test3", "test4", "test5", "test6", "test7", "test8", 
    "test9", "test10", "test11", "test12", "test13", "test14", "test15", 
    "test16", "test17", "test18", "test19", "test20" 
]; 

async function heavyProcessSimulator(item) { 
    setTimeout(() => { 
    console.log(item); 
    }, (Math.floor(Math.random() * 10000))); 
} 

items.forEach((item) => { 
    heavyProcessSimulator(item); 
}); 

Beispielausgabe:

test16 
test19 
test14 
test2 
test3 
test11 
test9 
test10 
... 

So stellen Sie sicher, dass das ecmascript Paket installiert (es ist standardmäßig mit Meteor 1.3+ Projekte sein sollte, aber nur im Fall: meteor add ecmascript).

Sie können Meteor async Unterstützung mit Funktionen aus dem async npm-Paket kombinieren. Hier ein überarbeiteter Anwendungsbeispiel: async.eachLimit:

Serverbeispiel:/server/main.js

import { Meteor } from 'meteor/meteor'; 
import async from 'async'; 

const items = [ 
    "test", "test2", "test3", "test4", "test5", "test6", "test7", "test8", 
    "test9", "test10", "test11", "test12", "test13", "test14", "test15", 
    "test16", "test17", "test18", "test19", "test20" 
]; 

async function heavyProcessSimulator(item, callback) { 
    Meteor._sleepForMs(Math.floor(Math.random() * 10000)); 
    console.log(item); 
    callback(); 
} 

async.eachLimit(items, 5, (item, callback) => { 
    try { 
    heavyProcessSimulator(item, callback); 
    } catch (e) { 
    return callback(e); 
    } 
}, (err) => { 
    if (err) console.error(err.message); 
}); 
+0

Danke für deine Antwort. Es funktioniert perfekt und jetzt ist mein Code async, aber ich brauche auch 'eachLimit' Limit-Verhalten, ich muss meinen Prozess fünf-mal-fünf ausführen. Wie kann ich damit umgehen? Ist es möglich mit 'erwarten'? – b24

+1

Ich habe meine Antwort überarbeitet, um zu zeigen, wie man die Async-Funktion von Meteor mit 'async.eachLimit' verwendet. – hwillson

+0

Hallo @hwillson, Vielen Dank für Ihre Wiederholung. Ich ändere meinen Code wie oben beschrieben. Async-Problem behoben, aber immer noch "Limit" funktioniert nicht. Ich bearbeite meine Frage mit einem neuen Abschnitt 'Bearbeiten' und füge neue Ausgabe hinzu. Ich ändere "console's" in 'heavyProcessSimulator', um das Problem zu beheben. – b24