2017-09-29 3 views
1

J'ai un tableau de 3 fonctions qui utilisent l'extraction de noeud pour extraire des données de 3 API différentes. Je voudrais invoquer seulement la deuxième et la troisième fonction si la première réponse de la fonction. Body contient 'rejeté'.Tableau de 3 fonctions de requête - comment appeler la deuxième fonction uniquement si la réponse de la première fonction contient une chaîne? - Noeud JS

Le problème auquel je suis confronté est que toutes les méthodes sont appelées avant que la réponse ne soit reçue du premier.

const buyersList = [ 
    { buyerName: 'ACME', 
    buyerPrice: '100', 
    buyerMethod: sellACME, 
    }, 
    { buyerName: 'ACME', 
    buyerPrice: '60', 
    buyerMethod: sellACME, 
    }, 
    { buyerName: 'ACME', 
    buyerPrice: '20', 
    buyerMethod: sellACME, 
    }, 
    { buyerName: 'ACME', 
    buyerPrice: '2', 
    buyerMethod: sellACME, 
    }, 
]; 

//fetch the data and parse 
function sellACME(url) { 
    return fetch(url, { method: 'POST' }) 
    .then(obj => parseResponse(obj)) 
    .catch(err => console.log(' error', err)); 
} 

//shift the first item in array and execute the method for first item. 
const methods = {}; 
methods.exBuyerSell = (url) => { 
    const currBuyer = buyersList.shift(); 
    return currBuyer.buyerMethod(url); 
}; 

//loop through array. 
module.exports = (url, res) => { 
    while (buyersList.length > 0) { 
    methods.exBuyerSell(url) 
    .then((buyerRes) => { 
     //if response.result is accepted, empty array, send response to client. 
     if (buyerRes.result === 'accepted') { 
     buyersList.length = 0; 
     res.json(buyerRes); 
     } 
     //if response.result is rejected, execute the next item in array. 
     if (buyerRes.result === 'rejected') { 
     methods.exBuyerSell(url); 
     } 
     return buyerRes; 
    }); 
    } 
}; 

La logique métier est que, si les données sont transmises au premier acheteur, les données est acceptée par cet acheteur et ne peut être présenté au deuxième acheteur.

setTimeout() n'est pas une option car la taille de la matrice peut atteindre 20 et chaque requête peut prendre jusqu'à 180 secondes.

J'ai essayé d'utiliser async/await et async.waterfall, mais j'ai toujours semblé avoir le même problème.

+0

j'ai mal compris votre problème le premier temps. Veuillez vérifier ma réponse mise à jour. J'espère que cela aide. –

Répondre

1

Ce concept peut être appliqué à votre propre cas d'utilisation. Il va parcourir la collection jusqu'à ce que la promesse décide:

pipePromises([2,4,6,1], calculateOddity).then(res => console.log(res)) 

function pipePromises(ary, promiser) { 
    return ary.slice(1, ary.size).reduce(
    (promise, n) => promise.catch(_ => promiser(n)), 
    promiser(ary[0]) 
); 
} 

function calculateOddity(n) { 
    return new Promise((resolve, reject) => { 
    n % 2 === 0 ? reject(n) : resolve(n); 
    }) 
} 
-1

Le problème est que fetch() retourne une promesse et ces promesses seront résolues ou rejetées dans un temps inconnu dans l'avenir.

"Le problème auquel je suis confronté est que toutes les méthodes sont invoquées avant que la réponse ne soit reçue du premier."

C'est parce que while est une fonction synchrone. Il va s'exécuter et n'attendra pas la réponse de la promesse fetch();

Le code ci-dessous ne s'arrêtera pas toutes les méthodes d'être invoquée lorsqu'une condition est satisfaite, mais il empêchera prématuré d'envoyer une réponse au client:

// modify this function and just return the promise from fetch() 
function sellACME(url) { 
    return fetch(url, { method: 'POST' }); 
} 


// on your loop, collect all the promises in 
// the done variable 
// then use Promise.all to traverse thru all 
// the promises returned by fetch once all of 
// promises are done executing 
module.exports = (url, res) => { 
    let done = []; 
    let result; 

    while (buyersList.length > 0) { 
     done.push(methods.exBuyerSell(url)); 
    } 

    Promise.all(done).then(values => { 
     values.forEach(function (value) { 
      if (value.result === "accepted") { 
       result = value; 
      } 
     }); 

     res.json(result); 
    }); 
}; 

Vérifiez MDN JavaScript Promise.all() Reference

+0

Je pense que vous avez mal compris le problème. OP doit effectuer seulement 1 demande. Si un fournisseur échoue, essayez avec le suivant. – nicooga