干净地兑现承诺

时间:2018-09-20 04:54:39

标签: javascript promise

编辑:结论审阅者得出的结论是,这是重复的错误,是由于对实际问题的误解而引起的。请查看该帖子底部的EDIT,以获取摘要和解决方案,以及对此问题的评论,以确认这实际上不是重复的内容。

原始问题: 我正在处理团队前端的后端通信逻辑。所有请求均遵循以下模式:

  1. 接受输入(可变)
  2. 预处理输入(对于所有输入都一致)
  3. 将输入发送到后端(可变,具有开发人员定义的条件逻辑)
  4. 后处理后端响应(对所有人一致)
  5. 将响应传递给前端的其余部分

我们最近偶然发现了几个失败失败的调用,经调查我们意识到问题是,逻辑的原始编写方式(通过promises)需要单独的.catch()调用,但在某些地方我们错过了

在查看此模块时,我还注意到它正在积累很多样板,主要是对后端的每次调用都写为:

function performOperation(input) {
  input = preprocess(input); // step 2
  return new Promise((resolve, reject) => {
    if (env.local) {
      resolve(/* logic to pull from local cache */);
    } else {
      thirdPartyFetchCall(input).then((response) => {
        resolve(response);
      }).catch((error) => {
        reject(error);
      });
    }
  }).then((output) => {
    return postprocess(output); // step 4
  }).catch((error) => {
    // this is for catching postprocess errors
    console.error(error);
  });
}

遵循此模式有几十个调用,我想对其进行一些清理,以及使最终的错误转储自动进行(由于位于同一线程中,因此可以对预处理进行有益,因此会自动记录其抛出,这不是后处理)。

我的想法是将其包装在一个Promise工厂中,开发人员可以按如下所示进行调用:

function performOperation(input) {
  return factory(input).send((processedInput) => {
    if (env.local) {
      return (/* logic to pull from local cache */);
    } else {
      return thirdPartyFetchCall(processedInput);
    }
  });
}

promise工厂将处理预处理和后处理调用,并转储后处理错误。问题是我不确定如何在保持逻辑独立性的同时从工厂知道thirdPartyFetchCall是会导致resolve还是reject。在传递给.then的函数返回时,我可以调用.catch.send,但是在env.local的情况下,它将返回一个非承诺值,并说服其他人与记住在链的末尾添加.catch的开发人员相比,手动分散它的错误发生的可能性较小。您如何建议我从工厂安全地处理它,只是测试对象是否是一个承诺?如果我只是从工厂内部对其调用resolve,则.catch子句是否仍会响应thirdPartyFetchCall引发的错误而触发,而没有在Promise中进行明确的reject调用宣言?这是上面的工厂代码示例:

function factory(input) {
  return new Promise((resolve, reject) => {
    return { send: (request) => {
      resolve(request(preprocess(input)));
    }
  }).then((output) => {
    return postprocess(output);
  }).catch((error) => {
    console.error(error);
  });
}

请注意,在上述工厂reject中,从未在promise声明中显式调用过,但是我仍然希望链末尾的catch能够对{{1 }}调用或postprocess函数返回的reject内的thirdPartyFetchCall调用。

编辑:好的,我现在觉得很蠢。整个工厂的想法使我误入歧途。当我真正的主要问题是request子句是否仍会在未在声明中显式调用拒绝的诺言上继续执行时,我陷入了实现细节。答案是肯定的,它将-我能够通过进一步简化测试并在节点中运行它来进行测试:

.catch()

0 个答案:

没有答案