Разрешать обещания один за другим (последовательность)? [Дубликат]

find /path -type f -exec grep -l "string" {} \;

Объяснение из комментариев

find - это команда, которая позволяет находить файлы и другие объекты, такие как каталоги и ссылки в подкаталогах заданного пути. Если вы не укажете маску, с которой должны встречаться имена файлов, она перечисляет все объекты каталога.

-type f specifies that it should proceed only files, not directories etc.
-exec grep specifies that for every found file, it should run grep command, passing its filename as an argument to it, by replacing {} with the filename
13
задан redgeoff 6 September 2014 в 22:06
поделиться

7 ответов

Просто используйте функцию $ q.when ():

var items = ['one', 'two', 'three'];
var chain = $q.when();
items.forEach(function (el) {
  chain = chain.then(foo(el));
});
return chain;

Примечание: foo должен быть фабрикой, например

function setTimeoutPromise(ms) {
  var defer = $q.defer();
  setTimeout(defer.resolve, ms);
  return defer.promise;
}

function foo(item, ms) {
  return function() {
    return setTimeoutPromise(ms).then(function () {
      console.log(item);
    });
  };
}

var items = ['one', 'two', 'three'];
var chain = $q.when();
items.forEach(function (el, i) {
  chain = chain.then(foo(el, (items.length - i)*1000));
});
return chain;
28
ответ дан redgeoff 22 August 2018 в 07:52
поделиться
  • 1
    Это не работает. Он выполняет их все одновременно. Я знаю это, потому что я выполняю серию запросов, которые занимают около 500 MS. наблюдая за моим сетевым трафиком, все они выходят одновременно (но по порядку). – FlavorScape 20 March 2015 в 00:45
  • 2
    @FlavorScape, убедитесь, что foo является фабрикой - см. Мои изменения. – redgeoff 20 March 2015 в 01:21
  • 3
    Ах, хорошо, сделав его фабрикой, делает так, чтобы он не выполнялся сразу в стеке вызовов, когда мы строим цепочку, не так ли? – FlavorScape 20 March 2015 в 01:50
  • 4
    Как я узнаю, когда все обещания в цепочке успешно разрешены? chain.then или $q.all(chain).then, похоже, не работают – Zbynek 6 October 2016 в 11:47
  • 5
    @Zbynek, в самом конце вы могли бы использовать chain.then(function () { console.log('all resolved'); }); – redgeoff 23 December 2016 в 16:25

Ваш ответ верный. Однако я подумал, что я бы предложил альтернативу. Вы можете быть заинтересованы в $ q.serial, если часто встречаетесь с обещаниями по цепочке.

var items = ['one', 'two', 'three'];
var tasks = items.map(function (el) {
  return function () { foo(el, (items.length - i)*1000)); });
});

$q.serial(tasks);

function setTimeoutPromise(ms) {
  var defer = $q.defer();
  setTimeout(defer.resolve, ms);
  return defer.promise;
}

function foo(item, ms) {
  return function() {
    return setTimeoutPromise(ms).then(function () {
      console.log(item);
    });
  };
}
1
ответ дан Bhargav Rao 22 August 2018 в 07:52
поделиться
  • 1
    Это выглядит интересно, я постараюсь реорганизовать после написания миллионных тестов на моей тарелке на сегодня ... – FlavorScape 6 April 2015 в 18:47
  • 2
    Это, безусловно, гораздо более простой подход, потому что легче читать код позже. – supersan 18 February 2017 в 17:06
  • 3
    $ q.serial - это несуществующая страница документа – Tony_Henrich 18 June 2018 в 20:07
  • 4
    Ссылка указывает на теневой веб-сайт, который пытается что-то установить. – theCrius 2 August 2018 в 11:22

Возможно, проще, чем ответ redgeoff , если вы не нуждаетесь в нем автоматизированным способом, вы можете сцепить обещания с помощью $q.when() в сочетании с .then(), как показано в начале этот пост . return $q.when() .then(function(){ return promise1; }) .then(function(){ return promise2; });

3
ответ дан Community 22 August 2018 в 07:52
поделиться

Я предпочитаю готовить функции, которые возвращают обещания с использованием angular.bind (или Function.prototype.bind), а затем связывают их с цепочкой с помощью сокращения ярлыка. Например,

// getNumber resolves with given number
var get2 = getNumber.bind(null, 2);
var get3 = getNumber.bind(null, 3);
[get2, get3].reduce(function (chain, fn) {
   return chain.then(fn);
}, $q.when())
.then(function (value) {
   console.log('chain value =', value);
}).done();
// prints 3 (the last value)
2
ответ дан gleb bahmutov 22 August 2018 в 07:52
поделиться
  • 1
    Не могли бы вы подробнее остановиться на angular.bind в этом сценарии? – pulkitsinghal 17 June 2015 в 16:01
  • 2
    Я использовал bind для создания функций, возвращающих обещание, которые не нуждаются в каких-либо аргументах. Таким образом, они могут быть использованы как .then(foo).then(bar) – gleb bahmutov 18 June 2015 в 16:18

Имея это:

let items = ['one', 'two', 'three'];

Одна строка (ну, 3 для читаемости):

return items
    .map(item => foo.bind(null, item))
    .reduce($q.when, $q.resolve());
4
ответ дан Jean-Baptiste Martin 22 August 2018 в 07:52
поделиться
var when = $q.when();

for(var i = 0; i < 10; i++){
    (function() {
         chain = when.then(function() {
        return $http.get('/data');
      });

    })(i); 
}
4
ответ дан pabloRN 22 August 2018 в 07:52
поделиться
  • 1
    Очень элегантный! Ты спас меня день :) – user3426603 9 May 2018 в 09:13

Redgeoff, ваш собственный ответ - это способ, которым я использовал для перевести массив в цепочку цепочек обещаний.

Созданный шаблон de facto выглядит следующим образом:

function doAsyncSeries(arr) {
    return arr.reduce(function (promise, item) {
      return promise.then(function(result) {
        return doSomethingAsync(result, item);
      });
    }, $q.when(initialValue));
}

//then
var items = ['x', 'y', 'z'];
doAsyncSeries(items).then(...);

Примечания:

  • .reduce является необработанным javascript, а не частью библиотеки.
  • result is предыдущий асинхронный результат / данные и включен для полноты. Начальным result является initialValue. Если нет необходимости передавать «результат», то просто оставьте его.
  • адаптируйте $q.when(initialValue) в зависимости от того, какой обетованный lib вы используете.
  • в вашем случае, doSomethingAsync есть foo (или что возвращает foo ()?) - в любом случае, функция.

Если вы похожи на меня, тогда картина будет выглядеть, на первый взгляд, как непроницаемая клаузула но как только ваш глаз будет настроен, вы начнете рассматривать его как старого друга.

Редактировать

Вот демон , предназначенный для демонстрации того, что шаблон, рекомендованный выше, фактически выполняет свои doSomethingAsync() вызовы последовательно, а не сразу при создании как указано в комментариях ниже.

34
ответ дан Roamer-1888 22 August 2018 в 07:52
поделиться
  • 1
    Первоначальный ответ не был синтаксически правильным. Я это исправил. Кроме того, для чего должен быть установлен initialValue? Как и вышеприведенный ответ, они будут срабатывать одновременно. – FlavorScape 20 March 2015 в 00:54
  • 2
    @FlavorScape, хороший улов. Приятно знать, что есть люди, проверяющие этот материал. – Roamer-1888 20 March 2015 в 09:57
  • 3
    initialValue появляется как result в первой итерации цикла reduce(). Это зависит от приложения. Если doSomethingAsync() не нуждается в предыдущем результате, переданном ему, то инициализатор сокращения упростит $q.when() – Roamer-1888 20 March 2015 в 10:06
  • 4
    @pulkitsinghal, вы можете прочитать мой вопрос Рекурсивно построить цепочку обещаний в соображениях javascript-памяти , которая на самом деле начинается с немного другой точки зрения, но привлекла два ответа, которые хорошо покрывают землю. – Roamer-1888 17 June 2015 в 18:43
  • 5
    Спасибо @ Roamer-1888 за краткое решение этой проблемы. – Deniz 16 July 2015 в 07:03
Другие вопросы по тегам:

Похожие вопросы: