resolve或reject之后还需要return吗?

作者:可木Changer 来源:www.jianshu.com 更新时间:2023-05-25 21:55

问:

假设我有如下的代码

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

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

  resolve(numerator / denominator);

 });
}

如果我的目的是利用reject提前退出,我是否应该在它之后也立刻加一个return呢?

答:

return的作用就在于rejection后终止函数的执行,并且阻止后面代码的执行。

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

    if (denominator === 0) {
      reject("Cannot divide by 0");
      return; //函数执行到此结束
    }

    resolve(numerator / denominator);
  });
}

在这个例子中它阻止了resolve(numerator / denominator);的执行,严格意义上这里是不需要return的。但是,仍然建议加上它来立刻阻止执行来避免一些潜在的麻烦。另外,避免执行不必要的代码是一个良好的实践。

背景

一个promise可以处于3种状态中的一种:

  1. pending - 初始状态。从pending状态我们可以切换到另外的状态
  2. fulfilled - 成功的操作
  3. rejected - 失败的操作

当一个promise是fulfilled或者rejected状态时,它将会一直维持该状态。所以,reject一个fulfilled的promise或者fulfill一个rejected的promise是没有任何效果的。

下面的代码片段展示了即使一个promise在rejected后被fulfill,那也是没什么卵用的。

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

// 输出结果
error:  Cannot divide by 0

所以我们为什么需要return?

尽管我们无法改变一个已经改变过状态的promise,但是reject和resolve都无法让函数剩下的部分暂停执行。那函数中包含的其他代码可能会对我们造成干扰。举例:

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));
// 输出结果
operation succeeded
error:  Cannot divide by 0

即使函数现在不包含这种代码,也保不齐将来会有。将来的重构者可能会弄不明白,也很难debug。

在resolve/reject后停止执行

这是标准JS控制流程:

  • resolve / reject 后return:
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));
  • return时带上 resolve / reject - 因为回调函数的return值是被忽略的,所以我们这里能少写一行代码:
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的方式的,这样代码看起来比较漂亮。