<div id="content"></div>
function call(func, ...args) {
  return { type: 'call', func, args };
}

function player() {
  var position = 0;

  return {
    moveLeft(steps) { position -= steps; },
    moveRight(steps) { position += steps; },
    getPosition() { return position; },
    save() {
      return new Promise(resolve => setTimeout(() => resolve('successful'), 1000));
    },
    jump() {
      throw new Error(`You ain't jump!`);
    },
    cheat() {
      return new Promise((resolve, reject) => {
        setTimeout(() => reject('sorry'), 1000);
      });
    }
  }
}

function* finish(player) {
  const position = yield call(player.getPosition);
  log(`The position is ${ position }.`);

  const resultOfSaving = yield call(player.save);
  log(`Saving is ${ resultOfSaving }.`);
}

function* game(player) {
  yield call(player.moveLeft, 2);
  yield call(player.moveRight, 1);
  // yield * finish(player);
  try {
    yield call(player.jump);
  } catch(error) {
    log(`Ops, ${ error }`);
  }
  try {
    yield call(player.cheat);
  } catch (error) {
    log(`Ops, ${ error }`);
  }
  yield call(finish, player);
  log('finish');
}

function receiver(generator) {
  return new Promise(generatorCompleted => {
    const iterate = function ({ value, done }) {
      if (done) { return generatorCompleted(value); }
      if (value.type === 'call') {
        try {
          const result = value.func(...value.args);

          if (result && typeof result.then !== 'undefined') {
            result.then(
              resolvedValue => iterate(generator.next(resolvedValue)),
              error => iterate(generator.throw(error))
            );
          } else if (result && typeof result.next !== 'undefined') {
            receiver(result).then(resultOfGenerator => {
              iterate(generator.next(resultOfGenerator))
            });
          } else {
            return iterate(generator.next(result));
          }
        } catch(error) {
          iterate(generator.throw(error));
        }
      }
    }
    iterate(generator.next());
  });
}

receiver(game(player()));

function log(...args) {
  console.log(...args);
  document.querySelector('#content').innerHTML += args + '<br />';
}
Rerun