JS - Выполнить обещания в порядке с $ q.when (), как мне добавить наконец?

1

Я создаю объекты с использованием внешнего источника с намерением обработать их стиль обратного вызова. К сожалению, эти обратные вызовы могут переместиться за пределы стека браузера, и я должен помнить о наихудшем сценарии 500 для IE.

Я переписал свой код с помощью $ q.when

   $scope.combinations.forEach(function(combination) {
        chain = chain.then(function() {
         return generateConfiguration(combination);
        });
    });

generateConfiguration, если функция возвращает обещание. Все работает отлично, но я хочу добавить finally() в конце цепочки.

То, что я сделал до сих пор, - это иметь трекер внутри generateConfiguration, который распознает последнюю комбинацию и запускает то, что должно было быть вызвано, наконец.

Есть ли более чистый способ сделать это?

  • 0
    Просто напишите chain.finally(…) после цикла?
Теги:
angular
callback
promise
q

2 ответа

1
Лучший ответ

Это зависит от того, что вы хотите сделать.

Вы создаете обещание цепи, так что если вы хотите сингл, finally, для цепи, просто добавьте его в конце после того, как строить его с этим forEach:

// ...your forEach here, then:
chain.finally(/*...*/);

Если вы хотите, finally выполнить каждое обещание от generateConfiguration, либо предоставите себе функцию-оболочку, либо сделайте это внутри обратного вызова forEach.

$scope.combinations.forEach(function(combination) {
    chain = chain.then(function() {
        return generateConfiguration(combination).finally(/*...*/); // <== 
    });
});

Сторона примечания: Там более идиоматический способ построить эту цепочку, посредством reduce:

var chain = $scope.combinations.reduce(function(chain, combination) {
    return chain.then(function() {
        return generateConfiguration(combination);
    });
}, Promise.resolve());

Добавление окончательного finally варианта (вариант № 1 выше):

var chain = $scope.combinations.reduce(function(chain, combination) {
        return chain.then(function() {
            return generateConfiguration(combination);
        });
    }, Promise.resolve())
    .finally(function() {
        // ...do stuff here...
    });
  • 1
    @TJ спасибо, что ваше первоначальное решение работает. Не уверен, почему я просто не попробовал это. О вашем предложении, почему оно лучше моего решения?
  • 0
    @CountGradsky: Не лучше, чем то, что это идиома для того, что возникло за последние 3-4 года. :-) Идиомы «хороши» или «лучше» только в том смысле, что они легко узнаваемы другими программистами, которые также знают идиому, что делает код легким для понимания.
Показать ещё 3 комментария
0

Да, есть: ввести $q (т.е. рамки обещаний) и переписать

$q.all($scope.combinations.map(function(combination) {
   return generateConfiguration(combination);
})).finally(function(res) {
   /* ... */
});

Таким образом, вы также будете отключать все generateConfiguration (s) параллельно (по крайней мере, как можно больше - например, ограничение на, например, XHR). В любом случае: $q.all(arrayOfPromises) может быть тем, что вы искали.

  • 1
    Разве это не меняет то, что делает код, хотя? Код OP обрабатывает обещания последовательно . Разве $q.all обрабатывает их параллельно (как стандартный Promise.all , который, я считаю, был вдохновлен q)?
  • 0
    $ q.all не работает для меня в этом сценарии Seb
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню