Здравствуйте. Пишу код с использованием Обещаний для последовательного запуска функций. Только пару дней как разбираюсь с ними для улучшения кода (ибо раньше была ёлочка из коллбэков); Так вот. Есть функция анимации вывода текста на экран Animal():
function Animal(string) {
var a = ''; //variable which will be entered character by character string
var i= 0;//Letter counter
var p = document.createElement('p');
$('body').scrollTop($('body').append(p).height());
return new Promise(function (resolve) {
Anima();
function Anima() {//Function of Animation
a+=string[i];
i++;
$('p').last().text(a);
var timer = setTimeout(Anima, 100);
if(i==string.length){
clearTimeout(timer);
resolve();
};
};
});
};
И функция AnimalPause() для изображения пауз(выводится на экран строка из точек и сразу же удаляется):
function AnimalPause(string) {
var a = ''; //variable which will be entered character by character string
var i= 0;//Letter counter
var p = document.createElement('p');
$('body').scrollTop($('body').append(p).height());
return promise = new Promise(function (resolve) {
Anima();
function Anima() {//Function of Animation
a+=string[i];
i++;
$('p').last().text(a);
var timer = setTimeout(Anima, 100);
if(i==string.length){
clearTimeout(timer);
$('p').last().remove();
resolve();
};
};
});
};
Все сделал, вроде бы. И, если выводить последовательно строки через .then() - всё работает. И, если выводить последовательно строки с использованием цикла - тоже всё работает:
Animal('..........')
.then(() => Animal('---Hello! CONSOLE v 1.0.1 is working!---'))
.then(() => Animal('To see all commands u can use type -help'))
.then(() => Animal('DONE'))
или так:
var chain = Promise.resolve();
pause.forEach(function(txt){
chain = chain.then(() => AnimalPause(txt))});
var pause = [
'...',
'.....',
'....',
'.........'
];
Но если через .then() Последовательно выводить текст, потом задержку, потом - текст, рушится: (Задержка выводится после того, как выведется текст):
function Hello() {
var chain = Animal('..........')
.then(() => Animal('---Hello! CONSOLE v 1.0.1 is working!---'))
.then(() => Animal('To see all commands u can use type -help'))
.then(function() {
return Pause(chain);
// pause.forEach(function(txt){
// chain = chain.then(() => AnimalPause(txt))})
})
.then(() => Animal('DONE'))
};
Hello();
function Pause (chain) {
return new Promise(function(resolve) {
pause.forEach(function(txt){
chain = chain.then(() => AnimalPause(txt))});
resolve();
})
}
Почему? Ну..и как исправить? :)
По совету @Grundy в комментарии скидываю код для тестирования
var pause = [
'...',
'.....',
'....',
'.........'
];
function Animal(string) {
var a = ''; //variable which will be entered character by character string
var i = 0; //Letter counter
var p = document.createElement('p');
$('body').scrollTop($('body').append(p).height());
return new Promise(function(resolve) {
Anima();
function Anima() { //Function of Animation
a += string[i];
i++;
$('p').last().text(a);
var timer = setTimeout(Anima, 100);
if (i == string.length) {
clearTimeout(timer);
resolve();
};
};
});
};
function AnimalPause(string) {
var a = ''; //variable which will be entered character by character string
var i = 0; //Letter counter
var p = document.createElement('p');
$('body').scrollTop($('body').append(p).height());
return promise = new Promise(function(resolve) {
Anima();
function Anima() { //Function of Animation
a += string[i];
i++;
$('p').last().text(a);
var timer = setTimeout(Anima, 100);
if (i == string.length) {
clearTimeout(timer);
$('p').last().remove();
resolve();
};
};
});
};
function Pause(chain) {
return new Promise(function(resolve) {
pause.forEach(function(txt) {
chain = chain.then(() => AnimalPause(txt))
});
resolve();
})
};
function Hello() {
var chain = Animal('..........')
.then(() => Animal('---Hello! CONSOLE v 1.0.1 is working!---'))
.then(() => Animal('To see all commands u can use type -help'))
.then(function() {
return Pause(chain); //Вы заметите, что строка пауз выводится после вывода на экран строки "DONE". Должно быть наоборот
})
.then(() => Animal('DONE'))
};
Hello();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Если пройтись по коду, то можно отметить, что функция Animal отличается от AnimalPause только тем, что в последней в итоге удаляется добавленный элемент.
Исходя из этого можно передавать созданный p
в resolve функции Animal
и удалять его если надо. При этом AnimalPause выродится в следующее
function AnimalPause(string) {
return Animal(string).then(p => p.remove());
};
Далее идет основная ошибка: функция Pause, которая добавляет продолжения для
var chain = Animal(...)
Но при этом не возвращает итоговый Promise, а просто переводит себя в состояние готово, именно поэтому выполнения вывода паузы откладывается до следующей цепочки.
Вместо этого нужно вернуть Promise собранный на основе массива pause с помощью функции reduce
function Pause(pause) {
return pause.reduce((chain, txt) => chain.then(() => AnimalPause(txt)), Promise.resolve());
};
В этом случае возвращенный Promise будет встроен в существующую цепочку и вызван в нужном порядке.
Пример в сборе:
var pause = [
'...',
'.....',
'....',
'.........'
];
function Animal(string) {
var a = ''; //variable which will be entered character by character string
var i = 0; //Letter counter
var p = document.createElement('p');
$('body').scrollTop($('body').append(p).height());
return new Promise(function(resolve) {
Anima();
function Anima() { //Function of Animation
a += string[i];
i++;
p.textContent = a;
var timer = setTimeout(Anima, 100);
if (i == string.length) {
clearTimeout(timer);
resolve(p);
};
};
});
};
function AnimalPause(string) {
return Animal(string).then(p => p.remove());
};
function Pause(pause) {
return pause.reduce((chain, txt) => chain.then(() => AnimalPause(txt)), Promise.resolve());
};
function Hello() {
var chain = Animal('..........')
.then(() => Animal('---Hello! CONSOLE v 1.0.1 is working!---'))
.then(() => Animal('To see all commands u can use type -help'))
.then(() => Pause(pause))
.then(() => Animal('DONE'))
};
Hello();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Всем приветПодскажите скрипт для загрузки больших файлов до 2 гб через ajax с возможность показа процента загрузки
Слабовато пока знаком с Jquery, сам найти ответ не сумел, возможно не там ищуНасколько я понял функция animate() принимает только конечные значения...