Javascript 我是否需要在提前解决/拒绝后返回?
假设我有以下代码Javascript 我是否需要在提前解决/拒绝后返回?,javascript,promise,es6-promise,Javascript,Promise,Es6 Promise,假设我有以下代码 function divide(numerator, denominator) { return new Promise((resolve, reject) => { if(denominator === 0){ reject("Cannot divide by 0"); return; //superfluous? } resolve(numerator / denominator); }); } 如果我的目标是使用reject提前退
function divide(numerator, denominator) {
return new Promise((resolve, reject) => {
if(denominator === 0){
reject("Cannot divide by 0");
return; //superfluous?
}
resolve(numerator / denominator);
});
}
如果我的目标是使用
reject
提前退出,我是否应该养成return
ing的习惯?return的目的是在拒绝后终止函数的执行,并防止在拒绝后执行代码
function divide(numerator, denominator) {
return new Promise((resolve, reject) => {
if (denominator === 0) {
reject("Cannot divide by 0");
return; // The function execution ends here
}
resolve(numerator / denominator);
});
}
在这种情况下,它阻止解析(分子/分母)代码>从执行开始,这不是严格需要的。但是,最好还是终止执行,以防止将来可能出现陷阱。此外,防止不必要地运行代码是一种很好的做法
背景
承诺可以处于以下三种状态之一:
挂起-初始状态。我们可以从待定状态转移到其他状态之一
完成-成功运营
拒绝-操作失败
当一个承诺被履行或拒绝时,它将无限期地保持这种状态(已解决)。因此,拒绝履行承诺或履行被拒绝的承诺将无效
这个示例片段显示,尽管承诺在被拒绝后得到了履行,但它仍然被拒绝
函数除法(分子、分母){
返回新承诺((解决、拒绝)=>{
如果(分母===0){
拒绝(“不能除以0”);
}
解析(分子/分母);
});
}
除以(5,0)
.then((result)=>console.log('result:',result))
.catch((错误)=>console.log('error:',error))代码>从技术上讲,此处不需要它1-因为承诺可以被唯一且仅一次地解决或拒绝。第一个承诺结果获胜,随后的每个结果都被忽略。这与节点样式回调不同
也就是说,在实际情况下,确保只调用一个是一种良好的干净实践,在这种情况下确实如此,因为没有进一步的异步/延迟处理决定“提前返回”与在任何功能完成后结束该功能无异-与继续进行无关或不必要的处理无异
在适当的时间返回(或使用条件避免执行“其他”情况)可减少意外地以无效状态运行代码或执行不必要的副作用的机会;因此,它使代码不太容易“意外中断”
1从技术上来说,这个答案还取决于这样一个事实:在这种情况下,如果省略“return”后面的代码,将不会产生副作用。JavaScript很乐意除以零并返回+Infinity/-Infinity或NaN。Ori的答案已经解释了不必返回
,但这是一种很好的做法。请注意,promise构造函数是抛出安全的,因此它将忽略稍后在路径中传递的抛出异常,本质上,您有一些不容易观察到的副作用
请注意,return
ing early在回调中也很常见:
function divide(nom, denom, cb){
if(denom === 0){
cb(Error("Cannot divide by zero");
return; // unlike with promises, missing the return here is a mistake
}
cb(null, nom / denom); // this will divide by zero. Since it's a callback.
}
因此,虽然这是承诺中的良好实践,但回调也是必需的。关于代码的一些注释:
- 您的用例是假设性的,不要实际使用同步动作的承诺
- 承诺构造函数忽略返回值。如果返回未定义的值,某些库将发出警告,以警告您返回该值的错误。大多数人并不那么聪明
- 承诺构造函数是抛出安全的,它会将异常转换为拒绝,但正如其他人所指出的,承诺只会解决一次李>
一个常见的习惯用法,可能是你喜欢的,也可能不是你喜欢的,就是将
返回
与拒绝
结合起来,同时拒绝承诺并退出函数,这样包括解析
在内的其余函数就不会执行。如果您喜欢这种风格,它可以使您的代码更加紧凑
function divide(numerator, denominator) {
return new Promise((resolve, reject) => {
if (denominator === 0) return reject("Cannot divide by 0");
^^^^^^^^^^^^^^
resolve(numerator / denominator);
});
}
这很好,因为承诺构造函数不使用任何返回值,并且在任何情况下resolve
和reject
都不返回任何值
同样的习惯用法也可以用于另一个答案中所示的回调样式:
function divide(nom, denom, cb){
if(denom === 0) return cb(Error("Cannot divide by zero"));
^^^^^^^^^
cb(null, nom / denom);
}
同样,这也很好,因为调用divide的人不希望它返回任何东西,也不处理返回值。如果在解析/拒绝后不“返回”,则在您打算停止后可能会发生错误(如页面重定向)。来源:我遇到了这个问题。在许多情况下,可以单独验证参数,并立即返回拒绝的承诺
函数除法2(分子、分母){
如果(分母===0){
返回承诺。拒绝(“不能除以0”);
}
返回新承诺((解决、拒绝)=>{
解析(分子/分母);
});
}
divide2(4,0)。然后((结果)=>console.log(结果),(错误)=>console.log(错误))代码>值得注意的是,如果返回值
存在或不存在,代码实际上不会有不同的行为,因为一旦设置了承诺状态,它就无法更改,因此在调用拒绝()
后调用解析()
除了使用一些额外的CPU周期外,不会执行任何操作。一、 从代码清洁度和效率的角度来看,我自己会使用return
,但在这个特定示例中不需要它。尝试使用Promise。尝试(()=>{})而不是新的Promise,并避免使用resolve/reject调用。相反,您可以只写返回分母===0?抛出“不能被零除”:分子/分母代码>我使用承诺。尝试作为一种启动承诺的手段,同时消除包含在try/catch块中的有问题的承诺。知道这一点很好,我喜欢这种模式。然而,此时是一个0阶段的建议,因此您只能使用或使用承诺库,如bluebird或Q.@jfriend00,显然在这个简单的例子中