Я думаю, что у меня есть приблизительное представление о том, чего вы пытаетесь достичь sh здесь, но, пожалуйста, дайте мне знать, если я что-то неправильно истолковал.
Предположим, вы хотите выполнить последовательность эффектов с некоторыми продолжительность между ними. Чтобы сохранить небольшой пример, мы будем использовать console.log
в качестве замены для любого эффекта, который вы хотите выполнить (например, установка innerHTML
элемента DOM).
Как В первом примере мы ждем 1 секунду, отображаем «Hello», затем ждем 1,5 секунды и отображаем «There»:
setTimeout(() => {
console.log('Hello');
setTimeout(() => {
console.log('There');
}, 1500);
}, 1000);
Мы можем уточнить это, описав общие части как функцию:
function logAfter(message, delay, callback) {
setTimeout(() => {
console.log(message);
if (callback) callback();
}, delay);
}
Тогда наш пример можно записать в виде:
logAfter('Hello', 1000, () => {
logAfter('There', 1500);
});
В качестве другого примера, который, возможно, более актуален для вашего проекта, вот как мы можем создать «l oop», который выполняет эффект несколько раз:
function logNAfter(message, times, delay, callback) {
if (times === 0 && callback) {
callback();
}
else {
setTimeout(() => {
console.log(message);
logNAfter(message, times-1, delay, callback);
}, delay);
}
}
Мы могли бы использовать это для отображения «Привет!» 3 раза, каждый разделенный на полсекунды, а затем отобразить «До свидания!» один раз, 2 секунды спустя:
logNAfter('Hi There!', 3, 500, () => {
logAfter('Goodbye!', 2000);
});
Теоретически вы можете создать произвольно длинную последовательность соответствующим образом распределенных эффектов таким образом. Однако я должен также упомянуть, что многие предпочли бы описать эти эффекты как Promise
s вместо:
function logAfter(message, delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(message);
resolve();
}, delay);
});
}
function logNAfter(message, times, delay) {
if (times === 0) {
return Promise.resolve();
} else {
return logAfter(message, delay)
.then(() => logNAfter(message, times-1, delay));
}
}
Первоначальными примерами стали:
logAfter('Hello', 1000)
.then(() => logAfter('There', 1500));
logNAfter('Hi There!', 3, 500)
.then(() => logAfter('Goodbye!', 2000));
Возможно, это лишь небольшое улучшение по сравнению с подходом в стиле обратного вызова, описанным выше, но гораздо понятнее, если вы сможете использовать async/await
:
async function logAfter(message, delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(message);
resolve();
}, delay);
});
}
async function logNAfter(message, times, delay) {
for (let i = 0; i < times; ++i) {
await logAfter(message, delay);
}
}
async function demoSequence1() {
await logAfter('Hello', 1000);
await logAfter('There', 1500);
}
async function demoSequence2() {
await logNAfter('Hi There!', 3, 500);
await logAfter('Goodbye!', 2000);
}
Надеюсь, что это поможет!