J'essaie d'enchaîner une séquence de Promise s pour que la deuxième promesse commence après la résolution de la première, etc. Je ne comprends pas comment je ne peux pas le faire fonctionner correctement.

Voici mon code de démonstration:

    const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'a'); });
    const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'b'); });
    const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'c'); });

    promise1.then(val => {
      console.log('promise 1', val);
      promise2.then(val2 => {
        console.log('promise 2', val2);
        promise3.then(val3 => {
          console.log('promise 3', val3);
        });
      });
    });

Donc, ce que j'attendais de ce code va comme ceci:

--- 5 seconds passes ---
// console outputs: 'promise 1a'
--- 5 seconds passes ---
// console outputs: 'promise 2b'
--- 5 seconds passes ---
// console outputs: 'promise 3c'

Mais à la place ce qui se passe:

--- 5 seconds passes ---
// console outputs: 'promise 1a'
// console outputs: 'promise 2b'
// console outputs: 'promise 3c'

Pourquoi est-ce ainsi? Pourquoi les trois promesses sont-elles déclenchées en même temps?

1
Dustexe 3 sept. 2020 à 15:48

2 réponses

Meilleure réponse

Pour expliquer pourquoi ils finissent tous en même temps, nous pouvons tout ignorer sauf les déclarations de promesse:

const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'a'); });
const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'b'); });
const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'c'); });

Ces promesses sont créées HOT (c'est-à-dire que le gestionnaire passé au constructeur est immédiatement appelé), et ont toutes été créées en même temps. Il s'ensuit que le setTimeout à l'intérieur se déclenchera dans 5 secondes, quelle que soit la façon dont ils seront utilisés par la suite.

La façon dont ils sont utilisés par la suite est accessoire à cela, cependant, pour que votre exemple fonctionne, il peut être préférable d'écrire des fonctions qui <^^return Promise lorsqu'elles sont appelées ... alors:

const getPromise1 = () => new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, 'a');
});
const getPromise2 = () => new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, 'b');
});
const getPromise3 = () => new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, 'c');
});

getPromise1().then((val1) => {
  console.log(val1);
  return getPromise2(); //by returning Promise, you can avoid deep nesting
}).then((val2) => {
  console.log(val2);
  return getPromise3();
}).then((val3) => {
  console.log(val3);
});

En réponse au commentaire, il peut être préférable d'avoir un tableau d'arguments qui sont utilisés pour alimenter une fonction de retour de Promise, puis d'utiliser async/await pour écrire une fonction qui appelle la fonction de retour de Promise dans l'ordre

const getPromise = (v) => new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, v);
});

async function run(params) {
  for (const p of params) {
    const returnVal = await getPromise(p);
    console.log(returnVal);
  }
}

run(['a', 'b', 'c']);
6
spender 3 sept. 2020 à 13:23

Les promesses commencent immédiatement après que vous les déclariez et la fonction .then() est juste un événement "onResolve", c'est-à-dire qu'elle est appelée lorsque la promesse est résolue. Pour faire ce que vous voulez, vous devrez utiliser un délai de 5, 10 et 15 secondes.

Si vous voulez quelque chose qui ne démarre que lorsque quelque chose l'appelle, recherchez RxJS. C'est une excellente bibliothèque qui possède des fonctions utiles pour résoudre et enchaîner les réponses. RxJS crée des observables qui ne démarrent que lorsque quelque chose s'y abonne .

0
Augusto César Bisognin 3 sept. 2020 à 13:04