在提前解决/拒绝后,我是否需要退货?

2022-08-29 23:39:59

假设我有以下代码。

function divide(numerator, denominator) {
 return new Promise((resolve, reject) => {

  if(denominator === 0){
   reject("Cannot divide by 0");
   return; //superfluous?
  }

  resolve(numerator / denominator);

 });
}

如果我的目标是提前退出,我是否应该养成事后立即退出的习惯?rejectreturn


答案 1

目的是在拒绝后终止函数的执行,并阻止其后代码的执行。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);

背景

承诺可以处于以下 3 种状态之一:

  1. 挂起 - 初始状态。从挂起状态,我们可以移动到其他状态之一
  2. 完成 - 成功运营
  3. 已拒绝 - 操作失败

当一个承诺被履行或拒绝时,它将无限期地停留在这种状态(已解决)。因此,拒绝已实现的承诺或履行被拒绝的承诺,将不会产生效果。

此示例代码段显示,尽管承诺在被拒绝后已实现,但它仍被拒绝。

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));

那么,我们为什么需要返回呢?

虽然我们无法更改已确定的 promise 状态,但拒绝或解析不会停止函数其余部分的执行。该函数可能包含会造成混淆结果的代码。例如:

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控制流的东西。

  • 返回后 / :resolvereject

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) {
      reject("Cannot divide by 0");
      return;
    }

    console.log('operation succeeded');

    resolve(numerator / denominator);
  });
}

divide(5, 0)
  .then((result) => console.log('result: ', result))
  .catch((error) => console.log('error: ', error));
  • 返回 / - 由于回调的返回值被忽略,我们可以通过返回 reject/resolve 语句来保存一行:resolvereject

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) {
      return 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));
  • 使用 if/else 块:

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) {
      reject("Cannot divide by 0");
    } else {
      console.log('operation succeeded');
      resolve(numerator / denominator);
    }
  });
}

divide(5, 0)
  .then((result) => console.log('result: ', result))
  .catch((error) => console.log('error: ', error));

我更喜欢使用其中一个选项,因为代码更扁平。return


答案 2

一个常见的成语,可能是也可能不是你的一杯茶,是将与,同时拒绝承诺并退出功能相结合,以便包括的功能的其余部分不被执行。如果你喜欢这种风格,它可以让你的代码更紧凑一些。returnrejectresolve

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) return reject("Cannot divide by 0");
                           ^^^^^^^^^^^^^^
    resolve(numerator / denominator);
  });
}

这工作正常,因为 Promise 构造函数不对任何返回值执行任何操作,并且在任何情况下都不返回任何内容。resolvereject

相同的习语可以与另一个答案中显示的回调样式一起使用:

function divide(nom, denom, cb){
  if(denom === 0) return cb(Error("Cannot divide by zero"));
                  ^^^^^^^^^
  cb(null, nom / denom);
} 

同样,这工作正常,因为调用的人不希望它返回任何内容,并且不会对返回值执行任何操作。divide