web-dev-qa-db-fra.com

En attente de plus d'une opération d'attente simultanée

Comment puis-je modifier le code suivant afin que les deux opérations asynchrones soient déclenchées et se voient offrir la possibilité de s'exécuter simultanément?

const value1 = await getValue1Async();
const value2 = await getValue2Async();
// use both values

Dois-je faire quelque chose comme ça?

const p1 = getValue1Async();
const p2 = getValue2Async();
const value1 = await p1;
const value2 = await p2;
// use both values
24
Ben

Je pense que cela devrait fonctionner:

 const [value1, value2] = await Promise.all([getValue1Async(),getValue2Async()]);

Vous trouverez ci-dessous un exemple plus détaillé au cas où cela vous aiderait à comprendre:

const promise1 = async() => {
  return 3;
}

const promise2 = async() => {
  return 42;
}

const promise3 = async() => {
  return 500;
  // emulate an error
  // throw "something went wrong...";
}

const f1 = async() => {

  try {
    // returns an array of values
    const results = await Promise.all([promise1(), promise2(), promise3()]);
    console.log(results);
    console.log(results[0]);
    console.log(results[1]);
    console.log(results[2]);

    // assigns values to individual variables through 'array destructuring'
    const [value1, value2, value3] = await Promise.all([promise1(), promise2(), promise3()]);

    console.log(value1);
    console.log(value2);
    console.log(value3);

  } catch (err) {
    console.log("there was an error: " + err);
  }

}

f1();

7
Kai

Utilisez .catch () et Promise.all ()

Assurez-vous de gérer correctement les rejets et de pouvoir utiliser Promises.all () en toute sécurité sans faire face à des rejets non gérés. (Édition: clarification par discussion: pas l'erreur unhandled rejection, mais simplement les rejets qui ne sont pas traités par le code. Promise.all() lèvera le premier rejet de promesse et ignorera le reste).

Dans l'exemple ci-dessous, un tableau de [[erreur, résultats], ...] est renvoyé pour faciliter le traitement des résultats et/ou des erreurs.

let myTimeout = (ms, is_ok) =>
  new Promise((resolve, reject) => 
    setTimeout(_=> is_ok ? 
                   resolve(`ok in ${ms}`) :
                   reject(`error in ${ms}`),
               ms));

let handleRejection = promise => promise
  .then((...r) => [null, ...r])
  .catch(e => [e]); 

(async _=> {
  let res = await Promise.all([
    myTimeout(100, true),
    myTimeout(200, false),
    myTimeout(300, true),
    myTimeout(400, false)
  ].map(handleRejection));
  console.log(res);
})();

Vous pouvez jeter de l'intérieur d'un catch () pour ne plus attendre (et ignorer les résultats du reste). Cependant, vous ne pouvez le faire qu'une fois par bloc try/catch, il est donc nécessaire de conserver un drapeau et de le contrôler aucune erreur non gérée ne se produit.

let myTimeout = (ms, is_ok) =>
  new Promise((resolve, reject) =>
    setTimeout(_=> is_ok ?
                   resolve(`ok in ${ms}`) :
                   reject(`error in ${ms}`),
               ms));

let has_thrown = false;

let handleRejection = promise => promise
  .then((...r) => [null, ...r])
  .catch(e => {
    if (has_thrown) {
      console.log('not throwing', e);
    } else {
      has_thrown = 1;
      throw e;
    }
  });

(async _=> {
  try {
    let res = await Promise.all([
      myTimeout(100, true),
      myTimeout(200, false),
      myTimeout(300, true),
      myTimeout(400, false)
    ].map(handleRejection));
    console.log(res);
  } catch(e) {
    console.log(e);
  }
  console.log('we are done');
})();

0
niry

Résout au lieu de promesses

const wait = (ms, data) => new Promise( resolve => setTimeout(resolve, ms, data) )
const reject = (ms, data) => new Promise( (r, reject) => setTimeout(reject, ms, data) )
const e = e => 'err:' + e
const l = l => (console.log(l), l)

;(async function parallel() {

  let task1 = reject(500, 'parallelTask1').catch(e).then(l)
  let task2 = wait(2500, 'parallelTask2').catch(e).then(l)
  let task3 = reject(1500, 'parallelTask3').catch(e).then(l)

  console.log('WAITING')

  ;[task1, task2, task3] = [await task1, await task2,  await task3]

  console.log('FINISHED', task1, task2, task3)

})()

Comme cela a été souligné dans d’autres réponses, une promesse rejetée peut donner lieu à une exception non gérée.
Celui-ci .catch(e => e) est un joli petit truc qui capte l’erreur et la transmet dans la chaîne, permettant ainsi à la promesse de devenir resolve au lieu de rejecting.

Si vous trouvez ce code ES6 moche, voyez plus convivial ici .

0
Qwerty