-
-
Save monochromer/812cc71b319b1ae64c1c8e325bd5ad88 to your computer and use it in GitHub Desktop.
/* | |
conf: Falsy Values 2015 | |
author: Kornel Lesinski | |
theme: And .then() what? Promise programming patterns | |
link: https://www.youtube.com/watch?v=KrhQE8K2I7Q | |
*/ | |
// 1 waterfall. Использование результатов предыдущих промисов | |
doFirst() | |
.then(firstResult => { | |
return doSecond() | |
.then(seondResult => { | |
return doThird() | |
.then(thirdResult => f(firstResult, seondResult, thirdResult)) | |
}) | |
}) | |
// 2 cache. Кеширование результатов асинхронных действий | |
const cache = new Map(); | |
function work(input) { | |
if (!cache.has(input)) { | |
const promise = asyncWork(input); | |
cache.set(input, promise); | |
}; | |
return cache.get(input); | |
} | |
// 3. serial queue. Последовательное выполнение промисов друг за другом | |
function serial(fnArray, onError, initialData) { | |
return fnArray | |
.reduce((p, f) => p.then(f), Promise.resolve(initialData)) | |
.catch(onError); | |
} | |
// 4. Часто запрашиваемые данные одного и того же ресурса | |
let currentPromise = null; | |
function currentWeather() { | |
if (!currentPromise) { | |
currentPromise = fetch('/url.json') | |
.then(res => res.json()) | |
.catch(err => console.log(err)) | |
.then(() => currentPromise = null); // finally | |
}; | |
return currentPromise; | |
} | |
// пример общей функции | |
function createBalanceLoadFunction(fn, onError) { | |
let currentPromise = null; | |
return function(...args) { | |
if (!currentPromise) { | |
currentPromise = fn(...args) // check if fn returns not promise | |
.catch(onError ? onError : console.error) | |
.finally(() => currentPromise = null); | |
}; | |
return currentPromise; | |
} | |
} | |
// 5. ready event. Работа с событиями | |
let DOM = { | |
ready: new Promise(resolve => { | |
document.addEventListener('DOMContentLoaded', function onDOMContentLoaded() { | |
document.removeEventListener('DOMContentLoaded', onDOMContentLoaded); | |
resolve(); | |
}); | |
}) | |
}; | |
DOM.ready.then(doYourWork); | |
// example === | |
/* | |
fetch(URL) | |
.then(res => res.json()) | |
.then(data => Object.keys(data).map(key => data[key])) | |
.then(result => console.log(result)) | |
.catch(error => console.error(`${error.message}, \n, ${error.stack}`)) | |
*/ | |
serial([ | |
(url) => fetch(url), | |
res => res.json(), | |
data => Object.keys(data).map(key => data[key]), | |
result => console.log(result) | |
], | |
error => console.error(`${error.message}, \n, ${error.stack}`), | |
URL | |
) | |
// https://uxdesign.cc/crafting-beautiful-ux-with-api-requests-56e7dcc2f58e | |
// timeout | |
class TimeoutError extends Error {} | |
function promiseWithTimeout(p, timeout = 5000) { | |
return Primise.race([ | |
p, | |
new Promise((resolve, reject) => { | |
setTimeout(reject, timeout, new TimeoutError(`It's timeout`)) | |
}) | |
]) | |
} | |
// Minimum wait time | |
// it protects your app from fast API responses. A min wait is a great pattern to use if you want to show a loading state to the user, but the API might respond quickly. Users will end up seeing loading states and data “pop” into view before they can focus on anything. | |
// retry | |
// Отменяемые промисы | |
// https://noteskeeper.ru/1385/ | |
// https://blog.bloomca.me/2017/12/04/how-to-cancel-your-promise.html | |
// Promise.allSettled | |
// https://github.com/jasonwilliams/proposal-promise-allSettled | |
// Promise.any | |
// Promise.some | |
/* | |
Promise.allSettled — это такой аналог Promise.all, который не реджектится если один из промисов зареджектился. | |
Я хотел бы предложить добавить еще два метода для работы с промисами — Promise.any и Promise.some. | |
Типичный юзкейс Promise.any — у нас есть несколько разных URL и мы хотим получить ответ от быстрейшего. | |
Может показаться, что для такой задачи подойдет Promise.race, но это не так. | |
Promise.race возвращает любой fulfilled промис, будь он resolved или reject. | |
Мы же хотим вернуть именно успешный, разрезолвленный промис и реджектнуть только если все промисы реджектнулись. | |
Promise.some принимает iterable первым параметром и число вторым. | |
Он возвращает массив разрезолвленных промисов указанной во втором параметре длины. | |
Если зареджектилось слишком много промисов (количество оставшихся промисов меньше, чем количество требуемых), | |
то Promise.some сразу же реджектится. | |
*/ | |
function any(promises) { | |
return Promise.all( | |
promises.map(promise => | |
promise.then(val => { throw val; }, _ => _), | |
), | |
).then(() => { throw Error('no successful connections'); }, _ => _); | |
} | |
// или (https://dev.to/vitalets/what-s-wrong-with-promise-allsettled-and-promise-any-5e6o) | |
const reverse = p => new Promise((resolve, reject) => Promise.resolve(p).then(reject, resolve)); | |
Promise.any = arr => reverse(Promise.all(arr.map(reverse))); | |
// композиция асинхронных функций | |
// https://github.com/HowProgrammingWorks/AsyncCompose | |
// | |
function microtaskDebounce(fn) { | |
let called = false | |
return () => { | |
if (called) { | |
return | |
} | |
called = true | |
window.Promise.resolve().then(() => { | |
called = false | |
fn() | |
}) | |
} | |
} |
тут ошибка, race не для этого
в чём ошибка?
В том что запустите ваш код и увидите что никакого таймаута нет. Race выдает первый выполненный промис.
Race выдает первый выполненный промис.
Race выдает promise, который первый поменял свое состояние. Если 2-ой промис завершится раньше, то мы должны поймать ошибку типа TimeoutError и отменить текущую операцию.
promiseWithTimeout(someAsyncOperation(), timeoutTime = 100)
.then((result) => console.log(result))
.catch((error) => {
if (error instanceof TimeoutError) {
console.log('need abort here async opertation')
return
}
throw error
})
Race выдает promise, который первый поменял свое состояние
Мы с вами видимо про разные таймауты говорим. Вы сами привели ссылку над функцией в которой реализован таймаут. Так вот там таймаут именно в понимании обязательной задержки выполнения, а у вас таймаут про который вы щас пишите - отмена по истечению времени. При этом вы вырвали описание таймаута которое под фукцией с того сайта и оно неправильное в случае того что вы мне сейчас описываете! Перечитайте все сами!
там таймаут именно в понимании обязательной задержки выполнения
Там это pattern2 (Minimum wait time).
У меня в конспекте pattern1 (Timeouts). Вот он из статьи:
О терминологии. Минимальное ожидание - это скорее delay. Время, после которого операция должна оборваться - timeout. Именно так называется параметр в XMLHttpRequest.
Минимальное ожидание - это скорее delay
Я согласен с тем что это скорее delay. Но у вас либо тут отсутсвует часть записи, либо просто нкпонятно к чему относится minimum wait time.
в чём ошибка?