重新构想异步/等待polyfills
#javascript #网络开发人员 #async #promises

我一直很好奇的一件事是:为什么要使用发电机来多填充异步/等待?

确保我可以考虑到它们在JavaScript中的工作方式,但是当有更好的选择时,为什么要使用该方法?

解决方案:只需写承诺

它尽可能简单。异步/等待的是句法糖的承诺链,所以为什么不将它们翻译成字面上:承诺链。

跟踪状态对象中的结果,即使在以后的延续功能中,您也可以访问它们。

唯一的缺点是您没有获得可变阴影,而是会得到可变的覆盖。但这可以通过使用Push'n'Pop机制使用类似堆栈的数据结构来琐碎地解决。

例子

让我演示我提出的替代方法,例如regenerator-runtime

简单的线性转换

async function fetchJson(url) {
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error("KO");
  }

  return response.json();
}

改变它应该给我们:

function fetchJson(url) {
  return fetch(url).then(response => {
    if (!response.ok) {
       throw new Error("KO");
    }

    return response.json();
  });
}

这几乎是逐条转换为简单的基于承诺的解决方案。

如果我们想制定转换制服,那么它可以给我们:

function fetchJson(url) {
  const state = {};
  return fetch(url).then(response => {
    state.response = response;

    if (!response.ok) {
       throw new Error("KO");
    }

    return response.json();
  });
}

需要以前的结果

async function stuff(input) {
  const response = await api.put(input);
  const extractedData = await extractData(response);
  return {
    response,
    data: extractedData,
  };
}

这应该变成:

function stuff(input) {
  const state = {};
  return api.put(input)
    .then(response => {
      state.response = response;
      return extractData(response);
    }).then(extractedData => {
      state.extractedData = extractedData;
      return {
        response: state.response,
        data: extractedData,
      };
    });
}

依赖范围的异常处理

async function stuff(input) {
  const response = await api.put(input);
  try {
    const extractedData = await extractData(response);
    return {
      response,
      data: extractedData,
    };
  } catch(e) {
    throw new ApiError(e, response);
  }
}

这应该变成:

function stuff(input) {
  const state = {};
  return api.put(input)
    .then(response => {
      state.response = response;
      return extractData(response).then(extractedData => {
        state.extractedData = extractedData;
        return {
          response,
          data: extractedData,
        };
      }).catch(e => {
        throw new ApiError(e, state.response);
      });
    });
}

您会注意到,只有在错误处理的情况下,我们实际上才需要筑巢。

最后

async function stuff(input) {
  const response = await api.put(input);
  try {
    const extractedData = await extractData(response);
    return {
      response,
      data: extractedData,
    };
  } catch(e) {
    throw new ApiError(e, response);
  } finally {
    logStuff(response);
  }
}

这应该变成:

function stuff(input) {
  const state = {};
  return api.put(input)
    .then(response => {
      state.response = response;
      return extractData(response).then(extractedData => {
        state.extractedData = extractedData;
        return {
          response,
          data: extractedData,
        };
      }).catch(e => {
        throw new ApiError(e, state.response);
      }).finally(() => {
        logStuff(state.response);
      });
    });
}

或,如果我们想避免使用Promise#finally并依靠初始提出的API:

function stuff(input) {
  const state = {};
  return api.put(input)
    .then(response => {
      state.response = response;
      const finallyFn = () => {
        logStuff(state.response);
      };
      return extractData(response).then(extractedData => {
        state.extractedData = extractedData;
        return {
          response,
          data: extractedData,
        };
      }).catch(e => {
        finallyFn();
        throw new ApiError(e, state.response);
      }).then(_$res => {
        finallyFn();
        return _$res;
      });
    });
}