用于执行javascript生成器的惯用模式

时间:2017-04-10 20:52:57

标签: javascript ecmascript-6 generator

我显然不了解发电机......

我有一个使用fetch

记录数据的生成器
function* log(logObject) {
  const params = {
    method: 'POST',
      body: JSON.stringify(logObject),
  };
  const response = yield fetch('/log', params);
  if (response.ok) {
    const json = response.json();
    return { json };
  }
  return { response };
}

我想从常规函数

执行此生成器
function doStuff(stuff) {
  if (hasIssues(stuff)) {
    const logGen = log({ data: { message: 'error log' } });
    return logGen.next().value;

    // but what if i add more yields to `log` in the future?  
    // i'll then need to modify this and every other function that calls `log` to have 2 calls to next()...
    // is there a way to just say, 'do all the things'?

  }
  ...
}

如何使我的代码足够灵活,以便生成器函数中的其他yields不要求我修改生成器的每次使用以包含对next()的其他调用?

我想我可以使用带有空块的for...of

for (let x of log({ data: { message: 'error log' } })) {}

但是有一个空的块循环看起来像代码味道......有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

您确实希望使用ES8 async / await来处理异步承诺使用代码。丢弃发电机。

async function log(logObject) {
  const params = {
    method: 'POST',
      body: JSON.stringify(logObject),
  };
  const response = await fetch('/log', params);
  if (response.ok) {
    const json = await response.json(); // don't forget to wait for the full body
    return { json };
  }
  return { response }; // are you sure you don't want to throw an error?
}

async function doStuff(stuff) { /*
^^^^^ this becomes asynchronous as well */
  if (hasIssues(stuff)) {
    const responseOrJson = await log({ data: { message: 'error log' } });
    …
  }
  …
}