Разорвать цепь Promise внутри цикла for - PullRequest
0 голосов
/ 24 февраля 2019

Я работаю над цепочкой обещаний, которая была вдохновлена ​​этим ответом: https://stackoverflow.com/a/44955506/7485805

Я хочу разорвать этот цикл for, чтобы правильно обработать отклонение цепочки.Я только что подумал, что не могу использовать break внутри .catch метода цепочки.

Вот мой код, если это поможет:

function pro (arr) {
  let chain = Promise.resolve();
  const self = {req: {}, res: {}};
  const length = arr.length;

  return new Promise((resolve, reject) => {
    for(let i=0; i<length; i++){
      chain = chain
          .then(() => arr[i].call(self) )
          .then(() => {
            if(i === (length - 1) )
              resolve();
          })
          .catch(e => {
            reject(e);
          })
    }
  })
  .then(() => {
    return self
  })
  .catch(e => {
    throw new Error (e);
  })

}

const x = function () {
  const self = this;
  return new Promise(resolve => {
    self.req = {key: "value"}
    resolve();
  })  
}

const y =  function () {
  const self = this;
  return new Promise((resolve, reject) => {
    console.log(self);
    reject();
  })
}

const z = function () {
  const self = this;
  return new Promise((resolve, reject) => {
    console.log('failed');
  })
}



pro([x, y, z])
.then((self) => {
  console.log('final',self);
})
.catch(e => {
  console.log('error', e);
})

x, y, z - это три функцииобъединены в функции pro Хотя x успешно разрешается, y выполняется, но отклоняется.

Я хочу остановить выполнение z, так как продолжение бессмысленно и может привести к ошибке вфактический код.

Кроме того, если кто-то может порекомендовать мне лучшую версию для этого фрагмента кода:

.then(() => {
  if(i === (length - 1) )
    resolve();
})

Примечание: я не могу использовать await, так как этот код будет выполняться сервером-сторона и использование await может заблокировать другие входящие запросы.

Ответы [ 3 ]

0 голосов
/ 25 февраля 2019

Несколько вещей: когда вы создаете свою цепочку обещаний внутри цикла for, это все, что происходит: цепочка создается.Выполнение .then произойдет как можно раньше в следующем цикле событий.Я попытаюсь проиллюстрировать:

var promiseChain = functionReturningPromise();
for(var i=0;i<3;i++){
  promiseChain = promiseChain.then(x=> {
    return anotherPromiseFunction(x);
  });
}

В зависимости от того, что на самом деле делает functionReturningPromise, что-то уже могло произойти в этот момент ... или, возможно, нет.Например, мы могли запустить fetch или, возможно, запустить WebWorker. Однако, если у нас было setTimeout вложенное внутри первого Promise, то все, что мы сделали, это поместили обратный вызов setTimeout в очередь дляследующий цикл цикла событий.Но гарантировано 100%, никакие функции .then еще не запущены.Это происходит позже, в следующем цикле событий.

Итак, следующий цикл событий приходит, и обещание выполнено.Это означает, что следующий .then будет запущен.Допустим, это не удается.В этот момент, поскольку мы связали обещания (promiseChain = promiseChain.then), мы сразу же пропускаем первый .catch (или .then со вторым параметром) в цепочке, и все промежуточные .then полностью пропускаются безказнены.Или, если catch нет, тогда эта цепочка обещаний выполнена.Нет необходимости в перерыве;это просто то, как работают Обещания.

Так что, если вы просто добавите .catch в самом конце цепочки, все хорошо.

Об этой вещи "цикла событий": I действительно рекомендую посмотреть Джейк Арчибальд: In The Loop , от JSConf.Asia 2018.

Также о await ... Звучит так, как будто есть некоторая путаница в том, каконо работает.Вы можете использовать только await внутри и async функции, поэтому вы никогда не сможете полностью заблокировать выполнение потока с помощью одного await.Это работает как цепочка .then s, просто синтаксический сахар.Так что @trincot определенно прав, с этим синтаксисом вы будете намного счастливее.

0 голосов
/ 25 февраля 2019

Вот альтернативный ответ, который просто выполняет обещания подряд, если только обещание не было отклонено, а затем остановлено.Это не использует await, но должно дать вам общее представление о том, как это можно сделать без него, но этот код также был написан очень быстро, так что это не самый оптимизированный код.

const x = function() {
  return new Promise(resolve => {
    resolve('it resolved ma!');
  });
};

const y = function() {
  const self = this;
  return new Promise((resolve, reject) => {
    reject("reject");
  });
};

const z = function() {
  const self = this;
  return new Promise((resolve, reject) => {
    resolve("never gets executed");
  });
};

function runPromises(promises) {
  const results = [];
  let count = 0;
  const executePromise = i => {
    count++;
    return promises[i]()
      .then((response) => {
        results.push(response);
        if (count !== promises.length) {
          executePromise(count);
        }
      })
      .catch((e) => {
        results.push(e);
        console.log("stop right now, thank you very much");
      });
  };
  if (Array.isArray(promises)) {
    executePromise(count);
  }
  return results;
}

const results = runPromises([x, y, z]);
console.log(results);
0 голосов
/ 24 февраля 2019

С синтаксисом async/await это сделать гораздо проще:

async function pro(arr) {
    const self = {req: {}, res: {}};
    for(const f of arr) await f.call(self);
    return self;
}

async function pro(arr) {
    const self = {req: {}, res: {}};
    for(const f of arr) await f.call(self);
    return self;
}

const x = function () {
  const self = this;
  return new Promise(resolve => {
    self.req = {key: "value"}
    resolve();
  })  
}

const y =  function () {
  const self = this;
  return new Promise((resolve, reject) => {
    console.log(self);
    reject("y failed");
  })
}

const z = function () {
  const self = this;
  return new Promise((resolve, reject) => {
  	console.log('failed');
  })
}

pro([x, y, z]).then((self) => {
  console.log('final',self);
})
.catch(e => {
  console.log('error', e);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...