Answers:
的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);
});
}
在这种情况下,它会阻止resolve(numerator / denominator);
执行,这不是严格需要的。但是,仍然最好终止执行以防止将来可能出现陷阱。另外,防止不必要地运行代码是一种很好的做法。
背景
一个承诺可以处于以下三种状态之一:
当一个诺言被兑现或被拒绝时,它会无限期地保持这种状态(结算)。因此,拒绝履行承诺或履行拒绝承诺将没有效果。
此示例代码段显示,尽管诺言在被拒绝后就已实现,但它仍然被拒绝。
function divide(numerator, denominator) {
return new Promise((resolve, reject) => {
if (denominator === 0) {
reject("Cannot divide by 0");
}
resolve(numerator / denominator);
});
}
divide(5,0)
.then((result) => console.log('result: ', result))
.catch((error) => console.log('error: ', error));
那么,为什么我们需要返回?
尽管我们无法更改已结算的承诺状态,但是拒绝或解决不会停止其余函数的执行。该函数可能包含会产生混乱结果的代码。例如:
function divide(numerator, denominator) {
return new Promise((resolve, reject) => {
if (denominator === 0) {
reject("Cannot divide by 0");
}
console.log('operation succeeded');
resolve(numerator / denominator);
});
}
divide(5, 0)
.then((result) => console.log('result: ', result))
.catch((error) => console.log('error: ', error));
即使函数现在不包含此类代码,这也会造成将来的陷阱。将来的重构可能会忽略以下事实:承诺被拒绝后,代码仍在执行,并且将很难调试。
解析/拒绝后停止执行:
这是标准的JS控制流程内容。
resolve
/ 之后返回reject
:resolve
/ 返回reject
-由于忽略了回调的返回值,我们可以通过返回reject / resolve语句保存一行:我更喜欢使用其中一个return
选项,因为代码比较扁平。
return
因为一旦设置了承诺状态,就无法更改它,因此调用resolve()
之后的调用reject()
除了使用几个额外的CPU周期外不会做任何事情。我本人return
将从代码的清洁度和效率的角度使用正义,但是在此特定示例中并不需要。
Promise.try(() => { })
而不是新的Promise,并避免使用解析/拒绝调用。相反,您可以写return denominator === 0 ? throw 'Cannot divide by zero' : numerator / denominator;
我用Promise.try
它来启动一个Promise并消除包装在try / catch块中的有问题的promise。
reject
那会花费很多钱,例如连接到数据库或API端点,该怎么办?这一切都是不必要的,并且会花费金钱和资源,特别是例如,如果您要连接到类似AWS数据库或API Gateway终端的对象。在那种情况下,您肯定会使用return来避免执行不必要的代码。
return
。
一个常见的习惯用法(可能是也可能不是您的一杯茶)是将return
与结合使用reject
,以同时拒绝Promise并退出功能,以便resolve
不执行功能的其余部分(包括)。如果您喜欢这种样式,则可以使您的代码更加紧凑。
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
者不希望它返回任何东西,也不对返回值做任何事情。
reject
身份没有错
从技术上讲,这里不需要1-因为Promise可以排他或仅一次解决或拒绝。第一个Promise结局获胜,随后的每个结果都将被忽略。这是不同的节点样式的回调。
话虽这么说,优良作法是确保在实际可行的情况下(在这种情况下)确实要正确调用一个,因为没有进一步的异步/延迟处理。“尽早返回”的决定与完成其工作后结束任何功能没有什么不同 -继续进行无关或不必要的处理。
在适当的时间返回(或以其他方式使用条件语句以避免执行“其他”情况)减少了意外地在无效状态下运行代码或执行不良副作用的机会;因此,它使代码不太容易“意外中断”。
1这个技术上的答案还取决于这样一个事实,在这种情况下,“返回”之后的代码(如果应省略)将不会产生副作用。JavaScript将愉快地除以零并返回+ Infinity / -Infinity或NaN。
如果您在解决/拒绝后不“返回”,则在您打算停止它之后,可能会发生坏事(例如页面重定向)。资料来源:我遇到了这个问题。
Ori的答案已经说明,没有必要 return
但这是一个好习惯。请注意,promise构造函数是安全抛出的,因此它将忽略在路径中稍后传递的抛出异常,从本质上讲,您有一些不容易观察到的副作用。
请注意,return
inging在回调中也很常见:
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.
}
因此,尽管在promises中是一种很好的做法,但回调是必需的。有关代码的一些注意事项:
在许多情况下,可以分别验证参数并立即通过Promise.reject(reason)返回被拒绝的promise 。
function divide2(numerator, denominator) {
if (denominator === 0) {
return Promise.reject("Cannot divide by 0");
}
return new Promise((resolve, reject) => {
resolve(numerator / denominator);
});
}
divide2(4, 0).then((result) => console.log(result), (error) => console.log(error));