2017-12-28 40 views
2
let currentProduct; 

for (let i = 0; i < products.length; i++) { 
    currentProduct = products[i]; 

    subscription.getAll(products[i]._id) 
     .then((subs) => { 
      update(subs, currentProduct); 
     }); 
} 

Ich verwende drossel, die Methoden getAll und Update Rückkehr verspricht. Wie kann ich sagen "Warte, bis die zwei Versprechen kommen, dann aktualisiere den aktuellen Produktwert"? Ich bin ganz neu in JS ...Warten Versprechen innen für Schleife

+0

Warum ist diese Frage async-abgefragt? Möchten Sie diese Funktion verwenden? – Bergi

Antwort

3

Diese einfach sein wird, wenn Sie async/await verwenden:

// Make sure that this code is inside a function declared using 
// the `async` keyword. 
let currentProduct; 

for (let i = 0; i < products.length; i++) { 
    currentProduct = products[i]; 

    // By using await, the code will halt here until 
    // the promise resolves, then it will go to the 
    // next iteration... 
    await subscription.getAll(products[i]._id) 
     .then((subs) => { 
      // Make sure to return your promise here... 
      return update(subs, currentProduct); 
     }); 

    // You could also avoid the .then by using two awaits: 
    /* 
    const subs = await subscription.getAll(products[i]._id); 
    await update(subs, currentProduct); 
    */ 
} 

Oder wenn Sie nur klares Versprechen verwenden können, können Sie eine Schleife durch alle Ihre Produkte, und setzen Sie jedes Versprechen in die .then der letzten Schleife. Auf diese Weise wird es nur bis zum nächsten vorrücken, wenn die vorherigen aufgelöst hat (obwohl es die ganze Schleife ersten iteriert haben wird):

let currentProduct; 

let promiseChain = Promise.resolve(); 
for (let i = 0; i < products.length; i++) { 
    currentProduct = products[i]; 

    // Note that there is a scoping issue here, since 
    // none of the .then code runs till the loop completes, 
    // you need to pass the current value of `currentProduct` 
    // into the chain manually, to avoid having its value 
    // changed before the .then code accesses it. 

    const makeNextPromise = (currentProduct) =>() => { 
     // Make sure to return your promise here. 
     return subscription.getAll(products[i]._id) 
      .then((subs) => { 
       // Make sure to return your promise here. 
       return update(subs, currentProduct); 
      }); 
    } 

    // Note that we pass the value of `currentProduct` into the 
    // function to avoid it changing as the loop iterates. 
    promiseChain = promiseChain.then(makeNextPromise(currentProduct)) 
} 

Im zweiten Schnipsel, die Schleife nur die gesamte Kette einrichtet, aber führt den Code innerhalb der .then nicht sofort aus. Ihre getAll Funktionen werden nicht ausgeführt, bis jede vorherige Lösung der Reihe nach gelöst wurde (was Sie wollen).

+1

Wenn Sie 'await' verwenden, würden Sie es auch anstelle des' then' Anrufs verwenden. – Bergi

+0

@Bergi Sie haben Recht. Du könntest warten verwenden, um das Ergebnis von "getAll" zu bekommen, und dann an "update" in der nächsten Zeile mit einem anderen warten. Aber was da ist, ist immer noch gültig und ich bin dafür bekannt, dass ich meine Erwartungen und Thesen mische und kombiniere. Ich würde sagen, dass es OPs Ermessen ist, welchen Stil er bevorzugt. – CRice

+0

Also zwei verschachtelte warten oder warten/dann, oder? – Jumpa

3

Hier ist, wie ich es tun würde:

for (let product of products) { 
    let subs = await subscription.getAll(product._id); 
    await update(subs, product); 
} 

Keine Notwendigkeit, manuell verketten Versprechen oder Iterierte Arrays von Index :)

+1

Ich habe versucht, Ihren Code und ich denke, es ist der elegantere. Wie auch immer, Sie vermissen "lassen" für das Produkt im Inneren. Das habe ich bemerkt, weil ich ein UnhandledPromiseRejectionWarning bekommen habe ... könntest du bitte deinen Code bearbeiten und etwas hinzufügen, um eine Ablehnung des Versprechens zu behandeln? Vielen Dank im Voraus. EDIT: vergiss ich sollte versuchen/fangen ... – Jumpa

2

Sie möchten, um verfolgen, welche Produkte Sie verarbeitet haben Denn wenn einer fehlschlägt, hast du keine Ahnung, wie viele erfolgreich waren, und du weißt nicht, was du korrigieren sollst (wenn du zurückwürfelst) oder es erneut versuchen.

Die async "Schleife" könnte eine rekursive Funktion sein:

const updateProducts = /* add async */async (products,processed=[]) => { 
    try{ 
    if(products.length===0){ 
     return processed; 
    } 
    const subs = await subscription.getAll(products[0]._id) 
    await update(subs, product); 
    processed.push(product[0]._id); 
    }catch(err){ 
    throw [err,processed]; 
    } 
    return await updateProducts(products.slice(1),processed); 
} 

Ohne async Sie Rekursion oder reduzieren können:

//using reduce 
const updateProducts = (products) => { 
    //keep track of processed id's 
    const processed = []; 
    return products.reduce(
    (acc,product)=> 
     acc 
     .then(_=>subscription.getAll(product._id)) 
     .then(subs=>update(subs, product)) 
     //add product id to processed product ids 
     .then(_=>processed.push(product._id)), 
    Promise.resolve() 
) 
    //resolve with processed product id's 
    .then(_=>processed) 
    //when rejecting include the processed items 
    .catch(err=>Promise.reject([err,processed])); 
} 

//using recursion 
const updateProducts = (products,processed=[]) => 
    (products.length!==0) 
    ? subscription.getAll(products[0]._id) 
     .then(subs=>update(subs, product)) 
     //add product id to processed 
     .then(_=>processed.push(products[0]._id)) 
     //reject with error and id's of processed products 
     .catch(err=>Promise.reject([err,processed])) 
     .then(_=>updateProducts(products.slice(1),processed)) 
    : processed//resolve with array of processed product ids 

Hier ist, wie Sie updateProducts nennen würde:

updateProducts(products) 
.then(processed=>console.log("Following products are updated.",processed)) 
.catch(([err,processed])=> 
    console.error(
    "something went wrong:",err, 
    "following were processed until something went wrong:", 
    processed 
) 
) 
Verwandte Themen