Skip to content

Instantly share code, notes, and snippets.

@monochromer
Last active August 19, 2022 09:56
Show Gist options
  • Save monochromer/812cc71b319b1ae64c1c8e325bd5ad88 to your computer and use it in GitHub Desktop.
Save monochromer/812cc71b319b1ae64c1c8e325bd5ad88 to your computer and use it in GitHub Desktop.
Паттерны использования promise (Promise Patterns)
/*
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()
})
}
}
@myrecs
Copy link

myrecs commented Jun 23, 2022

Минимальное ожидание - это скорее delay

Я согласен с тем что это скорее delay. Но у вас либо тут отсутсвует часть записи, либо просто нкпонятно к чему относится minimum wait time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment