2017-03-29 2 views
5
var myArray = [1, 2, 3, 4, 5, 6] 

function myPrommise(num){ 
    return new Promise(res => { 
    window.setTimeout(()=>{ 
     res( console.log("done: " + num) ) 
    },2000) 
    }) 
} 


myPrommise(myArray[0]) 
    .then(x => myPrommise(myArray[1])) 
    .then(x => myPrommise(myArray[2])) 
    .then(x => myPrommise(myArray[3])) 
    .then(x => myPrommise(myArray[4])) 
    .then(x => myPrommise(myArray[5])) 

Gerade jetzt, wenn ich die obige Anweisung ausführen, wird es nacheinander ausgeführt. In meinem tatsächlichen Anwendungsfall ist das Array dynamisch gefüllt und ich muss die myPromise() Funktion für jedes Mitglied in myArray ausführen.Wie man Versprechungen der Reihe nach ausführt, die Parameter von einem Array übergebend?

Wie kann ich eine "pausable loop" machen, die für jedes Element im Array eine Schleife bildet, myPromise ausführen und warten, bis das Versprechen gelöst ist, bevor mit der nächsten Iteration fortgefahren wird?

+1

Promise.All ist, was Sie –

+1

@JohnPeters Auf seiner eigenen wollen, ist das nicht genug, denn Es wird nicht sequenziell aufgelöst. – 4castle

Antwort

15

Sie können die wiederholte Anwendung von .then in einer Falte machen:

myArray.reduce(
    (p, x) => 
    p.then(_ => myPromise(x)), 
    Promise.resolve() 
) 

Bläuling, ein ausgezeichnetes Versprechen Bibliothek, die Sie verwenden sollten, wenn Sie nicht, auch has mapSeries built in:

Promise.mapSeries(myArray, myPromise) 

Runnable Schnipsel:

const myArray = [1, 2, 3, 4, 5, 6] 
 

 
const sleep = ms => 
 
    new Promise(res => { 
 
    setTimeout(res, ms) 
 
    }) 
 

 
const myPromise = num => 
 
    sleep(500).then(() => { 
 
    console.log('done: ' + num) 
 
    }) 
 

 
myArray.reduce(
 
    (p, x) => 
 
    p.then(_ => myPromise(x)), 
 
    Promise.resolve() 
 
)

+1

Wenn Sie alle Ergebnisse wie mit 'Promise.all' -' myArray.reduce ((p, x)) => p.then (Ergebnisse => fn (x) .then (r => results.concat (r))), Promise.resolve ([])). Then (results => {}); ' –

0

Ich würde babel verwenden und es auf diese Weise tun:

let args = [1, 2, 3]; 
 
    
 
    const myPromise = async x => console.log('arg:',x); 
 
    
 
    const test = async() => { 
 
     for (let task of args.map(myPromise)) 
 
     await task; 
 
    } 
 
    
 
    test().then(console.log('Done'));
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>

+1

Ich glaube, dass Ihr zweites Beispiel nicht garantiert sequentiell ausgeführt wird. –

1

Sie Array.reduce nutzen könnten.

//type: [number] 
var myArray = [1, 2, 3, 4, 5, 6] //doesn't really matter 

//type: number -> Promise<number> 
function myPromise(num){ 
    return new Promise((resolve) => { 
    window.setTimeout(()=>{ 
     resolve(console.log("done: " + num) ) 
    },2000) 
    }) 
} 

//Array.reduce has type: [a] ~> ((b, a) -> b), b) -> b 
//So it can have type: 
//[number] ~> ((Promise<number> -> number -> Promise<number>), Promise<number>) -> Promise<number> 
//Therefore we need to give reduce a function that takes a Promise 
//resolving to a number and a number which makes a new promise. 
//This is the function we want: 

function sequencePromises(promise, number) { 
    return new Promise((resolve) => { 
    resolve(promise.then(_ => myPromise(number))); 
    } 
} 

myArray.reduce(sequencePromises, Promise.resolve()); 

Natürlich ist dieser vereinfachenden Ansatz funktioniert nicht, wenn Sie ein Versprechen haben die Fehler kann, oder wenn Sie vorherige Ergebnisse benötigen, so dass Sie vielleicht sequencePromises allgemeinere machen wollen:

function genericSequencePromises(promiseFunction) { 
    return (promise, parameter) => { 
    return new Promise((resolve, reject) => 
         return promiseFunction(resolve, 
               reject, 
               promise, 
               parameter)); 
    } 
} 

Dann können Sie tun, was immer Sie wollen, solange Sie ein Versprechen abgeben.

Schließlich könnte man von diesem Helfer profitieren:

function promiseSeries(array, reducer) { 
    return array.reduce(reducer, Promise.resolve()); 
} 

es bringt alle zusammen:

let sequencePromises = genericSequencePromises((resolve, reject, promise, num) => { 
    resolve(promise.then(_ => console.log(`done: ${num}`))); 
} 

promiseSeries(myArray, sequencePromises); 

Auf diese Weise können Sie nicht nur den Fall in Frage behandeln, sondern viel mehr komplexe Fälle.

0

Sie können über die Anordnung von Elementen durchlaufen und die params wie dies passieren:

const arr = [1, 2, 3, 4, 5, 6]; 
 
const MyPromiseFunction = num => new Promise((resolve, reject) => { 
 
    // Your logic... 
 
    setTimeout(() => num <= 4 
 
    ? resolve('Success!') 
 
    : reject('Rejected!'), 1000 * num); 
 
}); 
 
const logMessage = (num, msg) => console.log(`For number ${num} promise result: ${msg}`); 
 

 
arr.forEach(
 
    num => MyPromiseFunction(num) 
 
    .then(message => logMessage(num, message)) 
 
    .catch(reason => logMessage(num, reason)) 
 
);

Verwandte Themen