Я собираюсь поделиться тем, что я нашел интересным в то время. Это возможность моделирования функции с асинхронным ожиданием с функциями генератора.
Для этого я собираюсь использовать следующую функцию в качестве примера.
function test() { asyncFn(function* () { const a = yield fetch("https://randomuser.me/api/"); const b = yield a.json(); console.log(JSON.stringify(b.results, null, 2)); }); }
Давайте представим, что мы хотим имитировать доходность, как если бы это было ожидание, и мы хотим напечатать результат вызова https://randomuser.me/api/.
Нам нужно сделать функцию, которая имеет в качестве входного параметра функцию-генератор, которая творит чудеса.
Мы можем начать с вызова самого генератора.
function asyncFn(gen) { const g = gen();
тогда мы можем добавить два метода, как если бы это был залог. onThen для then промиса и onError как перехват промиса в случае ошибки.
const onThen = (value) => { const newG = state.g.next(value); step({ ...state, g: newG }); }; const onError = (error) => { state.g.throw(error.message); };
И внутри них мы можем управлять, что бы собрать следующее значение, чтобы продолжить вычисление последующих значений или в случае ошибки выбросить исключение с ошибкой
Наконец, мы создаем, так сказать, внутреннее состояние, в котором мы храним генератор и различные функции, созданные ранее. И мы вызываем новую функцию для управления точкой, в которой мы находимся
const state = { g, onThen, onError }; step({ ...state, g });
Наконец, в ступенчатой функции мы контролируем, достигли ли мы конца генератора. А если нет, мы делаем значение генератора доступным, если полученное значение не является обещанием. И мы вызываем then или соответствующую ошибку.
function step(state) { if (state.g.done) { return undefined; } Promise.resolve(state.g.value) .then((value) => state.onThen(value)) .catch((error) => state.onError(error)); }
Наконец, давая в качестве окончательного результата что-то вроде этого.
function asyncFn(gen) { const g = gen(); const onThen = (value) => { const newG = state.g.next(value); step({ ...state, g: newG }); }; const onError = (error) => { state.g.throw(error.message); }; const state = { g, onThen, onError }; step({ ...state, g }); } function step(state) { if (state.g.done) { return undefined; } Promise.resolve(state.g.value) .then((value) => state.onThen(value)) .catch((error) => state.onError(error)); } function test() { asyncFn(function* () { const a = yield fetch("https://randomuser.me/api/"); const b = yield a.json(); console.log(JSON.stringify(b.results, null, 2)); }); } test();
Где мы можем использовать нашу функцию asyncFn, которая имитирует асинхронное ожидание с выходом