javascript - 以干净的方式包装承诺
问题描述
编辑:审稿人得出的关于这是重复的结论是错误的,并且源于对实际问题的误解。请参阅帖子底部的编辑以获取摘要和解决方案,以及对此问题的评论,确认这实际上不是重复的。
原始问题:我正在为我们团队的前端处理后端通信的逻辑。所有请求都遵循以下模式:
- 接受输入(可变)
- 预处理输入(与所有输入一致)
- 将输入发送到后端(不同,具有开发人员定义的条件逻辑)
- 后处理后端响应(对所有人都一致)
- 将响应传递给前端的其余部分
我们最近偶然发现了一些静默失败的调用,经过调查,我们意识到问题是最初编写逻辑的方式(通过承诺)需要一个单独的 .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);
});
}
遵循这种模式有几十个调用,我想稍微清理一下,以及使最终的错误转储自动(预处理受益于在同一个线程中,因此它的抛出被自动记录,后处理不是这种情况)。
我的想法是将它包装在一个承诺工厂中,然后开发人员可以如下调用:
function performOperation(input) {
return factory(input).send((processedInput) => {
if (env.local) {
return (/* logic to pull from local cache */);
} else {
return thirdPartyFetchCall(processedInput);
}
});
}
承诺工厂将负责预处理和后处理调用,以及转储后处理错误。问题是我不确定如何从工厂判断是否thirdPartyFetchCall
会导致resolve
或reject
同时保持逻辑独立。我可以在传递给的函数返回时调用.then
and ,但在 的情况下,它将返回一个非承诺值,并说服其他开发人员手动承诺它比记住在末尾添加链不太可能。您如何建议我从工厂安全地处理它,只需测试该对象是否是一个承诺?如果我只是从工厂内部调用它,该子句是否仍会触发以响应引发的错误.catch
.send
env.local
.catch
resolve
.catch
thirdPartyFetchCall
reject
在 Promise 声明中没有显式调用?这是与上述内容一起使用的工厂代码示例:
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
执行链末尾的 以响应postprocess
调用中抛出的错误或函数返回的 promise 中的reject
调用。thirdPartyFetchCall
request
编辑:好的,我现在觉得很愚蠢。整个工厂的想法让我误入歧途。.catch()
当我真正的主要问题是,如果在声明中没有明确调用拒绝的承诺,子句是否仍会触发,我陷入了实现细节。答案是肯定的,它会的——我可以通过进一步简化测试并在节点中运行它来进行测试:
function test() { throw 'error'; }
let p = new Promise((resolve, reject) => {
resolve(test());
}).then((r) => {
console.log('success');
}).catch((r) => {
console.log('error');
});
解决方案
推荐阅读
- javascript - 悬停在冻结列上时,SlickGrid 上的垂直滚动没有任何效果
- git - Github - 我是否需要多个 SSH 密钥用于不同的项目?(苹果系统)
- css - 是否可以通过 CDN 使用 Bootstrap 4 而不会接管整个风格?
- android - STATE_CONNECTED 并不意味着它真的是 CONNECTED?
- sql - oracle中创建表的方法
- python - 在 R 中使用带有网状结构的 python 时遇到问题
- kotlin - 使用 avro 的 Kotlin 应用程序配置 kafka 消费者和生产者失败
- python - 我有一个数据框,想要根据前一行填充所有空列值,并在另一列中使用相同的值?
- oracle - 无法在预期的位置找到 FROM 语句
- livecode - Livecode commandKeyDown 和 escapeKey 命令报错