Resolving Promises последовательно не работает - PullRequest
0 голосов
/ 15 мая 2019

У меня есть код для:

  • Чтение последних трех данных из Firebase
  • Итерация каждых полученных данных
  • Передача выражения функции, возвращающей обещание, в массивОбещание будет обработано последовательно позже
  • Обработать указанный массив последовательно

Код:

firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
  let promiseArray = [];
  
  snapshot.forEach(e => {
    promiseArray.push(() => {
      firebase.storage().ref(e.key).getDownloadURL().then(url => {
        //Do something with URL
        //In this case, I print out the url to see the order of URL retrieved
        //Unfortunately, the order was incorrect
        return 'Resolved, please continue'; //Return something to resolve my Promise
      });
    });
  });
  
  let result = Promise.resolve([]);
  promiseArray.forEach(promise => {
    result = result.then(promise);
  });
});

Я думаю, что это уже должно быть правильно.Однако результат, который я хочу получить, неверен.Что я пропустил?

РЕДАКТИРОВАТЬ

Кажется, я упустил пункт. В моем массиве Promise я хочу, чтобы первая функция разрешала Promise, который он возвращает первым, прежде чем перейти ко второй функции.

Ответы [ 3 ]

0 голосов
/ 15 мая 2019

Вы должны использовать reduce. Очень хороший пример вы найдете здесь: https://decembersoft.com/posts/promises-in-serial-with-array-reduce/

0 голосов
/ 15 мая 2019

Я разобрался: видимо, я забыл, чтобы моя функция не возвращала обещание.Из-за этого, когда я присоединяюсь к цепочке then s, он не ждет, пока мое Обещание разрешится первым, поскольку оно даже не было возвращено в первую очередь.Я в основном возвращаю пустоту, поэтому функции продолжаются, не дожидаясь разрешения предыдущего Обещания.Простое добавление return решает проблему:

firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
  let promiseArray = [];
  
  snapshot.forEach(e => {
    promiseArray.push(() => {
      return firebase.storage().ref(e.key).getDownloadURL().then(url => { //Add return here
        //Do something with URL
        //In this case, I print out the url to see the order of URL retrieved
        //Unfortunately, the order was incorrect
        return 'Resolved, please continue'; //Return something to resolve my Promise
      });
    });
  });
  
  let result = Promise.resolve([]);
  promiseArray.forEach(promise => {
    result = result.then(promise);
  });
});
0 голосов
/ 15 мая 2019

forEach - синхронный метод. Вы можете использовать map для создания массива обещаний, а затем использовать promise.all.

firebase.database().ref('someRef').limitToLast(3).on('value', snapshot => {
  let promiseArray = [];

  const promiseArray = snapshot.map(e => firebase.storage().ref(e.key).getDownloadURL());

  Promise.all(promiseArray).then((resultArr) => {
    // Do anything with your result array
  });
} 

Для последовательного выполнения обещаний вы можете использовать async await.

firebase.database().ref('someRef').limitToLast(3).on('value', async (snapshot) => {
    let promiseArray = [];

    const promiseArray = snapshot.map(e => firebase.storage().ref(e.key).getDownloadURL());
    let result;
    for(let i = 0; i < promiseArray.length; i++) {
        result = await promiseArray[i]; 
    }
});
...