Ich habe eine Schleife, die eine Methode aufruft, die asynchron arbeitet. Diese Schleife kann die Methode viele Male aufrufen. Nach dieser Schleife habe ich eine weitere Schleife, die nur ausgeführt werden muss, wenn alle asynchronen Aufgaben erledigt sind.
Das zeigt also, was ich will:
for (i = 0; i < 5; i++) {
doSomeAsyncStuff();
}
for (i = 0; i < 5; i++) {
doSomeStuffOnlyWhenTheAsyncStuffIsFinish();
}
Ich bin mit Versprechungen nicht sehr vertraut. Kann mir jemand helfen, dies zu erreichen?
So doSomeAsyncStuff()
verhalte ich mich :
function doSomeAsyncStuff() {
var editor = generateCKEditor();
editor.on('instanceReady', function(evt) {
doSomeStuff();
// There should be the resolve() of the promises I think.
})
}
Vielleicht muss ich so etwas machen:
function doSomeAsyncStuff() {
var editor = generateCKEditor();
return new Promise(function(resolve,refuse) {
editor.on('instanceReady', function(evt) {
doSomeStuff();
resolve(true);
});
});
}
Aber ich bin mir der Syntax nicht sicher.
s
am Ende keine gibtPromise
.Antworten:
Sie können dafür
Promise.all
( spec , MDN ) verwenden: Es akzeptiert eine Reihe einzelner Versprechen und gibt Ihnen ein einzelnes Versprechen zurück, das aufgelöst wird, wenn alle von Ihnen gegebenen Versprechen gelöst werden, oder abgelehnt wird, wenn eines von ihnen abgelehnt wird.Wenn Sie also
doSomeAsyncStuff
ein Versprechen zurückgeben, dann:const promises = []; // ^^^^^−−−−−−−−−−−−−−−−−−−−−−−−−−− use `const` or `let`, not `var` for (let i = 0; i < 5; i++) { // ^^^−−−−−−−−−−−−−−−−−−−−−−−− added missing declaration promises.push(doSomeAsyncStuff()); } Promise.all(promises) .then(() => { for (let i = 0; i < 5; i++) { // ^^^−−−−−−−−−−−−−−−− added missing declaration doSomeStuffOnlyWhenTheAsyncStuffIsFinish(); } }) .catch((e) => { // handle errors here });
MDN hat einen Artikel über Versprechungen hier . Ich beschreibe auch Proms ausführlich in Kapitel 8 meines Buches JavaScript: The New Toys , Links in meinem Profil, wenn Sie interessiert sind.
Hier ist ein Beispiel:
function doSomethingAsync(value) { return new Promise((resolve) => { setTimeout(() => { console.log("Resolving " + value); resolve(value); }, Math.floor(Math.random() * 1000)); }); } function test() { const promises = []; for (let i = 0; i < 5; ++i) { promises.push(doSomethingAsync(i)); } Promise.all(promises) .then((results) => { console.log("All done", results); }) .catch((e) => { // Handle errors here }); } test();
Beispielausgabe (aufgrund dessen kann das
Math.random
, was zuerst endet, variieren):quelle
Math.floor(Math.random() * 1000)
zu(i * 1000)
await
befindet, in dem dies zulässig ist. Im Moment können Sie nurawait
eineasync
Funktion verwenden. (Irgendwann können Sie es auch auf der obersten Ebene der Module verwenden.)Eine wiederverwendbare Funktion funktioniert gut für dieses Muster:
function awaitAll(count, asyncFn) { const promises = []; for (i = 0; i < count; ++i) { promises.push(asyncFn()); } return Promise.all(promises); }
OP-Beispiel:
awaitAll(5, doSomeAsyncStuff) .then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results)) .catch(e => console.error(e));
Ein verwandtes Muster iteriert über ein Array und führt für jedes Element eine asynchrone Operation aus:
function awaitAll(list, asyncFn) { const promises = []; list.forEach(x => { promises.push(asyncFn(x)); }); return Promise.all(promises); }
Beispiel:
const books = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }]; function doSomeAsyncStuffWith(book) { return Promise.resolve(book.name); } awaitAll(books, doSomeAsyncStuffWith) .then(results => console.log('doSomeStuffOnlyWhenTheAsyncStuffIsFinished', results)) .catch(e => console.error(e));
quelle
const doSomeAsyncStuff = async (funcs) => { const allPromises = funcs.map(func => func()); return await Promise.all(allPromises); } doSomeAsyncStuff([ () => new Promise(resolve => setTimeout(() => resolve(), 100)), () => new Promise(resolve => setTimeout(() => resolve(), 100)), () => new Promise(resolve => setTimeout(() => resolve(), 100)), () => new Promise(resolve => setTimeout(() => resolve(), 100)), () => new Promise(resolve => setTimeout(() => resolve(), 100)), ]);
quelle
Hier ist Code, den ich für mich selbst geschrieben habe, um die hier angegebenen Antworten zu verstehen. Ich habe Mungo-Abfragen in einer for-Schleife, also setze ich hier die
asyncFunction
, um ihren Platz einzunehmen. Hoffe es hilft jedem. Sie können dieses Skript im Knoten oder in einer von vielen Javascript-Laufzeiten ausführen.let asyncFunction = function(value, callback) { setTimeout(function(){console.log(value); callback();}, 1000); } // a sample function run without promises asyncFunction(10, function() { console.log("I'm back 10"); } ); //here we use promises let promisesArray = []; let p = new Promise(function(resolve) { asyncFunction(20, function() { console.log("I'm back 20"); resolve(20); } ); }); promisesArray.push(p); for(let i = 30; i < 80; i += 10) { let p = new Promise(function(resolve) { asyncFunction(i, function() { console.log("I'm back " + i); resolve(i); } ); }); promisesArray.push(p); } // We use Promise.all to execute code after all promises are done. Promise.all(promisesArray).then( function() { console.log("all promises resolved!"); } )
quelle
/*** Worst way ***/ for(i=0;i<10000;i++){ let data = await axios.get( "https://yourwebsite.com/get_my_data/" ) //do the statements and operations //that are dependant on data } //Your final statements and operations //That will be performed when the loop ends //=> this approach will perform very slow as all the api call // will happen in series /*** One of the Best way ***/ const yourAsyncFunction = async (anyParams) => { let data = await axios.get( "https://yourwebsite.com/get_my_data/" ) //all you statements and operations here //that are dependant on data } var promises = [] for(i=0;i<10000;i++){ promises.push(yourAsyncFunction(i)) } await Promise.all(promises) //Your final statement / operations //that will run once the loop ends //=> this approach will perform very fast as all the api call // will happen in parallal
quelle