Я собираюсь поделиться тем, что я нашел интересным в то время. Это возможность моделирования функции с асинхронным ожиданием с функциями генератора.

Для этого я собираюсь использовать следующую функцию в качестве примера.

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, которая имитирует асинхронное ожидание с выходом