Всем привет!
Есть более глобальная задача, но реализовал ее на простом тесте, где результат идентичен. Простой пример. Считаем суммы арифметической прогрессии в цепочке последовательных промисов. В реальности вместо прогрессии считается довольно длительный (несколько секунд) процесс, поэтому в арифметическую прогрессию вставлен псевдо-delay для эмуляции данной ситуации. Выводим результат на страницу. Код:
$(document).ready(function()
{
TestFunc();
});
//Арифметическая прогрессия
function arithmeticProgression(n)
{
delay(100);
return (n !== 0) ? n + arithmeticProgression(n-1) : 0;
}
//Эмуляция задержки
function delay(ms)
{
var date = Date.now();
var curDate = null;
do
{
curDate = Date.now();
} while (curDate-date < ms);
}
//Тестовая функция
function TestFunc()
{
const counter = 10;
$('body').html('');
for (var i = 0; i < counter; i++)
{
$('body').append($("<div id='" + i + "'>i=" + i + "<span> Новый</span></div>"));
}
//Начало цепочки промисов
let chain = Promise.resolve();
var results = [];
for(let i=0; i<counter; i++)
{
chain = chain.then(function()
{
$('#' + i + ' span').text(' В процессе');
return TestPromise(i, 0);
})
.then(function(result)
{
$("#" + i + " span").text(' ' + result);
results.push(result);
});
}
chain.then(function()
{
console.log('All done!');
});
}
//Промис расчета арифметической прогрессии
function TestPromise(n, delay)
{
delay = delay || 0;
return new Promise(function(resolve)
{
/*setTimeout(function()
{
resolve("arithmetic progression(1, " + n + ")=" + arithmeticProgression(n));
}, delay);*/
resolve("arithmetic progression(1, " + n + ")=" + arithmeticProgression(n));
});
}
Если оставить в таком виде (закоменчен SetTimeout в промисе арифметической прогрессии), то поведение следующее: при загрузке страницы все виснет (в отладчике js даже не подгружается) до тех пор, пока все не отработает. То есть такое ощущение, что цепочка промисов блокирует основной поток выполнения. Хотя промисы же сами по себе асинхронны. А вот, если включить таймауты (даже с 0 задержкой), то все начинает работать, как надо: прогрессии считаются одна за одной асинхронно - основной поток не виснет.
Уже наизусть практически выучил
эту статью. Но все равно такое ощущение, что я в корне чего-то не понимаю в промисах.
Цепочка промисов составлена на основании решения
этой задачи + поиск в просторах интернета.
P.S. Сделал сразу образец для просмотра в песочнице:
1 вариант (когда все висит и результат выдается разом)
2 вариант (когда работает так, как нужно)
P.P.S. Хотя даже во втором варианте наблюдается некая нелинейность выполнения (некоторые результаты выдаются с задержкой, некоторые быстрее). Явно тут дело не в разности "сложности" вычисления арифметической прогрессии от 0 до 1 и от 0 до 10.