unhandledrejection
В браузері вбудовано багато подій, наприклад mousemove
- рух миші. Щоб додати функцію-підписник на певну подію, використовують метод addEventListener
:
var i = 1;
window.addEventListener("mousemove", (event) => {console.log(i++)});
Вбудовані асинхронні методи типу fetch
aбо setTimout
, також генерують свого роду події: “надійшов результат запиту”, або “пройшло n мілісекунд”. Важливою деталлю є те що функція-підписник не виконується одразу при настанні події, а лише поміщується в чергу задач. В залежності від завантаженості черги на той момент, може бути додаткова затримка між постановкою в чергу і власне виконанням:
// тут setTiemout гарантує що функція fn буде виконана
// НЕ РАНІШЕ ніж через 1 секунду, але можливо трохи пізніше
setTimeout(
function fn() {
console.log(
'Я виконаюсь не раніше ніж через 1 секунду (але можу і пізніше)!'
);
},
1000
);
Повернемось до промісів. Конструктор проміса примає один аргумент - функцію-ініціалізатор. Ця функція виконується одразу при створенні проміса, і в свою чергу очікує в якості аргументів дві функції - одну для переводу проміса в стан fulfilled
, а іншу - для переводу в rejected
. Наприклад, створимо функцію-аналог setTimout
, яка повертатиме проміс (до речі, цей процес називається “промісифікацією” функції):
function runWithTimeout(fn, miliseconds) {
// Створюємо і повертаємо проміс
return new Promise(
function(resolve, reject) {
// В ініціалізаторі маємо два шляхи: викликати resolve() або reject(),
setTimeout(
function () {
try {
// Викликаємо що треба через задану кількість часу
var result = fn();
// І "резолвимо" проміс з отриманим результатом
resolve(result)
} catch(err) {
// А у випадку помилки - "реджектимо" проміс з обʼєктом помилки
reject(err);
}
},
miliseconds
)
}
)
}
Тепер, уявимо як її можна було б використовувати:
// Виведемо чотири літери, кожну через секунду після попередньої
runWithTimeout(
() => console.log('A'),
1000
).then(
() => runWithTimeout(
() => console.log('B'),
1000
)
).then(
() => runWithTimeout(
() => console.log('C'),
1000
)
).then(
() => runWithTimeout(
() => console.log('D'),
1000
)
);
Уявіть як це виглядало би без промісів:
// Це жах!
setTimeout(
() => {
console.log('A');
setTimeout(
() => {
console.log('B');
setTimeout(
() => {
console.log('C');
setTimeout(
() => {
console.log('D');
},
1000
);
},
1000
);
},
1000
);
},
1000
);