2017-10-05 4 views
0
avant de passer

j'ai une obligation de faire ce qui suit:JavaScript promesses - En attente de

  1. obtenir une liste des « lignes » en appelant une fonction interne (getLines()).
  2. Sélectionnez la première ligne, effectuer une action
  3. Après la fin de l'action précédente, sélectionnez la ligne suivante et faire la même action
  4. Répétez l'opération pour toutes les lignes (3-20 en fonction de l'utilisateur)

J'ai le code suivant à la place:

App.Lines = response.data;  
for (var _i = 0; _i < App.Lines.length; _i++) { 
    var makeCallPromise = new Promise(
     function(resolve, reject) { 
      Session.connection.ol.makeCall(App.Lines[_i], callBackFunction(response) { 
       //this can take up to 30 seconds to respond... 
       resolve(response.data); 
      }, errorCallBackFunction(message) { 
       reject(message.error); 
      }, bareJid); 
     } 
    ) 
    makeCallPromise.then(function(fulfilled) { 
     console.log("PROMISE WORKED!!!!!", fulfilled); 
    }) 
    .catch(function(error) { 
     console.log("PROMISE FAILED!!!!!", error); 
    }); 
} 

Mon espoir était que la boucle attendrait pour résoudre la promesse avant qu'elle poursuit la boucle, cependant, ce n'est pas le cas. Ma question est de savoir s'il est possible ou non d'arrêter la boucle jusqu'à ce que la résolution soit complète. Remarque - J'utilise la librairie bluebird JS pour les promesses. Merci!

Cordialement,

Gary

+0

Je pense que vous devez 'return' la promesse d'une certaine façon. Comme dans ce cas, «satisfait» est la phrase clé que vous utilisez dans votre promesse. – ZombieChowder

+0

Au lieu de boucler le tout, bouclez makeCallPromise et placez ces promesses dans un tableau. Ensuite, utilisez Promise.all (tableau) et ajoutez les appels 'then()' après la promesse.all. Le résultat sera que toutes les promsies seront résolues avant que le premier 'then()' ne soit appelé, ainsi toutes les données sont disponibles pour une nouvelle boucle.Sinon, n'utilisez pas du tout de boucle, mais effectuez le makeCallPromise suivant après que le premier a été résolu. – Shilly

+0

@Shilly Merci, j'ai essayé d'utiliser cela dans la réponse fournie par marvel308, avec Promise.each(). Ma réponse est là sur ce que j'ai fait et ce qui s'est passé. – Gary

Répondre

0

Vous pouvez utiliser Promise.each() fourni par Bluebird, il traverserait un tableau en série et d'attendre pour eux de résoudre avant de passer à l'élément suivant du tableau

+0

J'ai essayé d'utiliser en itérant sur les promesses et en en créant un tableau (plutôt que de les résoudre dans l'itération). J'ai ensuite appelé 'Promise.each (promiseArray, function (résultat) {console.log (résultat)}. Then (fonction (remplie) {console.log ("WORKED")}). Catch (function (error) { console.log ("ERROR")})); '. Le problème est que cela ne fonctionne pas, il essaie toujours de faire les deux Session.connection.ol.makeCall sans attendre le premier à résoudre. – Gary

+0

Avez-vous utilisé bluebird? – marvel308

+0

Hmm J'ai chargé la bibliothèque bluebird en l'incluant dans

0

I Je ne sais pas à propos de bluebird, mais vous pouvez faire quelque chose comme ça pour créer une sorte de boucle for qui attend que chaque promesse se termine avant la prochaine itération.

Voici un exemple générique, il pourrait certainement être optimisé, il est juste une tentative rapide:

var i = 0; 
var performAsyncOperation = function(operationNumber) { 
    return new Promise(function(resolve, reject){ 
    console.log('Operation number', operationNumber); 
    resolve(); 
    }); 
} 

var chainAsyncOperations = function() { 
    if(++i < 10) { 
     return performAsyncOperation(i).then(chainAsyncOperations); 
    } 
}; 
performAsyncOperation(i).then(chainAsyncOperations); 

En espérant que cela vous aidera;)

0

Ce cas d'utilisation correspond parfaitement à la fonction ES7 async await, Si vous avez la possibilité de transpile votre code à l'aide babeljs, vous pouvez factoriser votre fonction comme ceci:

function createPromise(line) { 
    return new Promise(
     function(resolve, reject) { 
      Session.connection.ol.makeCall(line, callBackFunction(response) { 
       //this can take up to 30 seconds to respond... 
       resolve(response.data); 
      }, errorCallBackFunction(message) { 
       reject(message.error); 
      }, bareJid); 
     } 
    ); 
} 

App.Lines = response.data; 

async function main() { 
    for (var _i = 0; _i < App.Lines.length; _i++) { 
     try { 
      var result = await createPromise(App.Lines[_i]); 
      console.log(result); 
     } catch (err) { 
      console.log(err); 
     } 
    } 
} 

main().then(function() { 
    console.log('finished'); 
}); 
0

vous devez utiliser Bluebird#each méthode:

.each (function (tout élément, int index, longueur int) itérateur) -> Promise

itérer sur un tableau ou une promesse d'un tableau, qui contient des promesses (ou mélange de promesses et de valeurs) avec la fonction d'itération donnée avec la signature (valeur, index, longueur) où valeur est la valeur résolue d'une promesse respective dans le tableau d'entrée. L'itération se produit en série. Si une promesse dans le tableau d'entrée est rejetée, la promesse retournée est également rejetée.

Promise.each(App.Lines, line => { 
    return new Promise((resolve, reject) => { 
     Session.connection.ol.makeCall(line, callBackFunction(response) { 
      resolve(response.data); 
     }, errorCallBackFunction(message) { 
      reject(message.error); 
     }, bareJid); 
    }) 
    .then(fulfilled => console.log("PROMISE WORKED!!!!!", fulfilled)) 
    .catch(err => onsole.log("PROMISE FAILED!!!!!", err)); 
}); 
+0

Salut, cela ne fonctionne pas, je ne comprends pas vraiment ce qu'il fait. Dans un cas simple de valeur 1 ligne, il semble que l'émission de 'Session.connection.ol.makeCall' deux fois dans le même moment, nous obtenons instantanément un échec. Quand je mets à jour ceci à 2 lignes, il émet 4 'Session.connection.ol.makeCall' dans un moment, puis plus tard il en émet 2 de plus après que la réponse revienne. – Gary

+0

Selon le code de votre question, 'App.Lines' est un tableau de lignes, dans mon code j'utilise la méthode' Bluebird # each' pour itérer sur ce tableau et appeler 'Session.connection.ol.makeCal' pour chaque ligne. Êtes-vous sûr que 'App.Lines' a une ligne (un élément) dans le premier cas et deux lignes dans le second? Ajoutez 'console.log (App.Lines.length)' avant 'Promise.each'. – alexmac