创建被拒绝的 JS 承诺的正确方法是什么?
What is a proper way to create a JS promise that is rejected?
如果只是为了试验 JS Promises 或 Promise.race() 等,需要创建一个被拒绝的 promise:
p = Promise.reject(Error("some unknown reason"));
但是这样一来,就会抛出异常。如果你沉默错误:
p = Promise.reject(Error("some unknown reason")).catch(err => {});
然后 p
实际上将是一个已解决的承诺。这是为什么?应该以这种方式创建被拒绝的承诺,还是应该做什么?如果使用 Promise.resolve(1)
.
,已解决的承诺会简单得多
创建被拒绝的承诺的正确方法是这样的:
let p = Promise.reject(new Error("some unknown reason"));
在某个地方,在您 return 回到事件循环之前,您需要对任何被拒绝的承诺有一个 .catch()
处理程序。如果您不这样做,系统将警告您有未处理的拒绝。这就是 Javascript 语言实现的状态。设计人员认为,不要让未处理的承诺拒绝被忽视是非常重要的(我同意 - 就像未处理的同步异常不会被忽视一样)。而且,在 JS 引擎的当前状态下,它们对未处理拒绝的检测略有不完善。有可能你可能会用那个被拒绝的承诺做一些事情,即 LATER 添加一个 .catch()
处理程序,但 JS 引擎不知道你以后要做什么。它只知道你已经回到了事件循环,而你还没有这样做。这看起来很麻烦,所以它会警告你。
如果你在上面放一个 .catch()
,那么承诺会接受你 return 或从 .catch()
处理程序中抛出的任何东西(就像 try/catch
在同步世界)。所以,如果你这样做:
let p = Promise.reject(new Error("some unknown reason")).catch(err => {});
然后,您在 .catch()
和 return 中捕获了拒绝,或者没有从中抛出任何东西,因此承诺链现在已通过 undefined
解析值解析。那里没有 .catch()
的要求,但是如果您有特定的理由添加 .catch()
(例如记录或清理代码或检查错误以确定正确的操作过程),但您想要promise 链以同样的原因被拒绝,那么你必须 return 一个新的被拒绝的 promise 或像这样抛出原始错误:
let p = Promise.reject(new Error("some unknown reason")).catch(err => {
// do whatever you want here
console.log(err);
throw err; // rethrow to keep the promise chain rejected
});
或者像这样:
let p = Promise.reject(new Error("some unknown reason")).catch(err => {
// do whatever you want here
console.log(err);
return Promise.reject(err); // return rejected promise to keep the promise chain rejected
});
但是,您需要对该承诺做一些事情,以便在某种承诺链上下文中使用它,最终将有一个真正的 .catch()
处理程序。
例如(你提到Promise.race),你可以这样做:
function delay(t,v) {
return new Promise(resolve => {
setTimeout(resolve, t, v);
});
}
let p1 = Promise.reject(new Error("You got rejected!!"));
let p2 = delay(100, "Got a good result");
Promise.race([p1, p2]).then(result => {
console.log(result);
}).catch(err => {
console.log(err.message);
});
这里不会有关于未处理的承诺拒绝的警告,因为我们将 p1
承诺(被拒绝)插入到 Promise.race()
中并且上面有一个 .catch()
处理程序.
Then p actually will be a resolved promise. Why is that?
因为您有一个空的 .catch()
没有 return 处理程序拒绝的承诺或没有抛出异常。所以,拒绝是 "caught" 和 "handled" 并且承诺链现在回到解决状态。由于 .catch()
处理程序没有 return 值,承诺链的解析值现在是 undefined
.
Is a rejected promise supposed to be created this way, or what should be done?
是的,这是创建拒绝承诺的正确方法。但是,你需要用它做点什么,而不是让它自己坐在那里。最终用它完成的事情(return 从一些承诺链中处理它或将其他处理程序链接到它)需要尽快发生(就像在解释器返回事件循环之前)。如果您用真实代码展示了一个真实世界的用例,我们可以更好地建议如何处理这个问题。
如果只是为了试验 JS Promises 或 Promise.race() 等,需要创建一个被拒绝的 promise:
p = Promise.reject(Error("some unknown reason"));
但是这样一来,就会抛出异常。如果你沉默错误:
p = Promise.reject(Error("some unknown reason")).catch(err => {});
然后 p
实际上将是一个已解决的承诺。这是为什么?应该以这种方式创建被拒绝的承诺,还是应该做什么?如果使用 Promise.resolve(1)
.
创建被拒绝的承诺的正确方法是这样的:
let p = Promise.reject(new Error("some unknown reason"));
在某个地方,在您 return 回到事件循环之前,您需要对任何被拒绝的承诺有一个 .catch()
处理程序。如果您不这样做,系统将警告您有未处理的拒绝。这就是 Javascript 语言实现的状态。设计人员认为,不要让未处理的承诺拒绝被忽视是非常重要的(我同意 - 就像未处理的同步异常不会被忽视一样)。而且,在 JS 引擎的当前状态下,它们对未处理拒绝的检测略有不完善。有可能你可能会用那个被拒绝的承诺做一些事情,即 LATER 添加一个 .catch()
处理程序,但 JS 引擎不知道你以后要做什么。它只知道你已经回到了事件循环,而你还没有这样做。这看起来很麻烦,所以它会警告你。
如果你在上面放一个 .catch()
,那么承诺会接受你 return 或从 .catch()
处理程序中抛出的任何东西(就像 try/catch
在同步世界)。所以,如果你这样做:
let p = Promise.reject(new Error("some unknown reason")).catch(err => {});
然后,您在 .catch()
和 return 中捕获了拒绝,或者没有从中抛出任何东西,因此承诺链现在已通过 undefined
解析值解析。那里没有 .catch()
的要求,但是如果您有特定的理由添加 .catch()
(例如记录或清理代码或检查错误以确定正确的操作过程),但您想要promise 链以同样的原因被拒绝,那么你必须 return 一个新的被拒绝的 promise 或像这样抛出原始错误:
let p = Promise.reject(new Error("some unknown reason")).catch(err => {
// do whatever you want here
console.log(err);
throw err; // rethrow to keep the promise chain rejected
});
或者像这样:
let p = Promise.reject(new Error("some unknown reason")).catch(err => {
// do whatever you want here
console.log(err);
return Promise.reject(err); // return rejected promise to keep the promise chain rejected
});
但是,您需要对该承诺做一些事情,以便在某种承诺链上下文中使用它,最终将有一个真正的 .catch()
处理程序。
例如(你提到Promise.race),你可以这样做:
function delay(t,v) {
return new Promise(resolve => {
setTimeout(resolve, t, v);
});
}
let p1 = Promise.reject(new Error("You got rejected!!"));
let p2 = delay(100, "Got a good result");
Promise.race([p1, p2]).then(result => {
console.log(result);
}).catch(err => {
console.log(err.message);
});
这里不会有关于未处理的承诺拒绝的警告,因为我们将 p1
承诺(被拒绝)插入到 Promise.race()
中并且上面有一个 .catch()
处理程序.
Then p actually will be a resolved promise. Why is that?
因为您有一个空的 .catch()
没有 return 处理程序拒绝的承诺或没有抛出异常。所以,拒绝是 "caught" 和 "handled" 并且承诺链现在回到解决状态。由于 .catch()
处理程序没有 return 值,承诺链的解析值现在是 undefined
.
Is a rejected promise supposed to be created this way, or what should be done?
是的,这是创建拒绝承诺的正确方法。但是,你需要用它做点什么,而不是让它自己坐在那里。最终用它完成的事情(return 从一些承诺链中处理它或将其他处理程序链接到它)需要尽快发生(就像在解释器返回事件循环之前)。如果您用真实代码展示了一个真实世界的用例,我们可以更好地建议如何处理这个问题。