Динамическое последовательное выполнение обещаний - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть динамическое число обещаний, которые мне нужно выполнять последовательно. Я понял, как я могу выполнять последовательные обещания, но мне не удается сделать его динамичным с рядом обещаний, которые могут варьироваться.

Вот способ, который я нашел, чтобы делать это статически Как разрешать обещания одно за другим? :

function waitFor(timeout) {
	return new Promise(function(resolve, reject) {
		setTimeout(function() {
			resolve(`Finished waiting ${timeout} milliseconds`);
		}, timeout);
	});
}

waitFor(1000).then(function(result) {
	$('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
    return waitFor(2000);
}).then(function(result) {
    $('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
    return waitFor(3000);
}).then(function(result) {
	$('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="result"></div>

Я хотел бы сделать то же самое, но вместо 3-х вложенных обещаний, я хотел бы иметь любое число, которое я хочу. Вы можете мне помочь ?

Большое спасибо !!

Ответы [ 4 ]

0 голосов
/ 30 апреля 2018

Забудьте, что я прокомментировал (когда вы конвертируете Promise в Observable или включаете обещание в массив, Promise выполняется). Вы можете использовать «рекурсивную» функцию

  foolPromise(index: number, interval: number) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({ id: index, data: new Date().getTime() % 100000 });
      }, interval);
    })
  }
  intervals: number[] = [1000, 50, 500];
  recursive(req: any, index: number) {
    req.then(res => {
      console.log(res);
      index++;
      if (index < this.intervals.length)
        this.recursive(this.foolPromise(index, this.intervals[index]), index);
    })
  }

  ngOnInit() {
    this.recursive(this.foolPromise(0, this.intervals[0]), 0)
  }
0 голосов
/ 29 апреля 2018

Создайте отдельную функцию для обработки количества итераций

function waitFor(timeout) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(`Finished waiting ${timeout} milliseconds`);
        }, timeout);
    });
}
function resultHandler(result) {
    $('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
    return waitFor(2000);
}
function repeat(promise,num){
    if(num>0)
    repeat(promise.then(resultHandler),num-1);
}

repeat(waitFor(1000),2)
0 голосов
/ 30 апреля 2018

Существует три основных способа решения этой задачи с помощью Обещаний.

  1. .reduce() шаблон.

function waitFor(timeout) {
	return new Promise(function(resolve, reject) {
		setTimeout(function() {
			resolve(`Finished waiting ${timeout} milliseconds`);
		}, timeout);
	});
}

var timeouts = [1000, 2000, 2000, 3000, 1000],
    sequence = tos => tos.reduce((p,c) => p.then(rp => waitFor(c))
                                           .then(rc => console.log(`${rc} @ ${new Date().getSeconds()}`)), Promise.resolve());

sequence(timeouts);
  1. Рекурсивный шаблон.

function waitFor(timeout) {
	return new Promise(function(resolve, reject) {
		setTimeout(function() {
			resolve(`Finished waiting ${timeout} milliseconds`);
		}, timeout);
	});
}

var timeouts = [1000, 2000, 2000, 3000, 1000],
    sequence = ([to,...tos]) => to !== void 0 && waitFor(to).then(v => (console.log(`${v} @ ${new Date().getSeconds()}`), sequence(tos)));

sequence(timeouts);
  1. Сканирование по левому шаблону.

Шаблон scanl будет последовательно выполнять обещания один за другим, но после его выполнения у вас также будет доступ к временным разрешениям обещаний. Это может быть полезно в некоторых случаях. Если вы собираетесь строить асинхронную древовидную структуру лениво (ветвление от узлов только при необходимости), вам нужно иметь доступ к предыдущим разрешениям обещаний.

Чтобы достичь функциональности scanl в JS, сначала мы должны реализовать ее.

var scanl = (xs, f, acc) => xs.map((a => e => a = f(a,e))(acc))

мы передаем scanl с помощью xs, который является массивом тайм-аутов в этом конкретном примере, f, который является функцией обратного вызова, которая принимает acc (аккумулятор) и e (текущий элемент) и возвращает новый аккумулятор. Значения накопителя (временные разрешения) отображаются в массиве тайм-аутов, к которому необходимо обращаться при необходимости.

function waitFor(timeout) {
	return new Promise(function(resolve, reject) {
		setTimeout(function() {
			resolve(`finished waiting ${timeout} milliseconds`);
		}, timeout);
	});
}

var timeouts = [1000, 2000, 2000, 3000, 1000],
    scanl    = (xs, f, acc) => xs.map((a => e => a = f(a,e))(acc)),
    proms    = scanl(timeouts,                                             // input array
                     (a,t,r) => a.then(v => (r = v, waitFor(t)))           // callback function
                                 .then(v => (console.log(`${r} and ${v}`),
                                             `${r} and ${v}`)),
                     Promise.resolve(`Started with 0`));                   // accumulator initial value

// Accessing the previous sub sequential resolutions
Promise.all(proms)
       .then(vs => vs.forEach(v => console.log(v)));
.as-console-wrapper {
max-height: 100% !important
}
0 голосов
/ 29 апреля 2018

Если вам не нужна сериализация, вы можете использовать Promise.all https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Promise.all([promise1, promise2, promise3]).then(function(values) {
  // do something with values
}).catch(function(err) {
  // error called on first failed promise
});

Или вы можете использовать асинхронную функцию:

async function doSomething(arrayOfPromises) {
  for (const item of arrayOfPromises) {
    const result = await item;
    // now do something with result
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...