Skip to content

promise/always-return Suspicious ​

What it does ​

Require returning inside each then() to create readable and reusable Promise chains. We also allow someone to throw inside a then() which is essentially the same as return Promise.reject().

Why is this bad? ​

Broken Promise Chain. Inside the first then() callback, a function is called but not returned. This causes the next then() in the chain to execute immediately without waiting for the called function to complete.

Examples ​

Examples of incorrect code for this rule:

javascript
myPromise.then(function(val) {});
myPromise.then(() => {
  doSomething();
});
myPromise.then((b) => {
  if (b) {
    return "yes";
  } else {
    forgotToReturn();
  }
});

Examples of correct code for this rule:

javascript
myPromise.then((val) => val * 2);
myPromise.then(function(val) {
  return val * 2;
});
myPromise.then(doSomething); // could be either
myPromise.then((b) => {
  if (b) {
    return "yes";
  } else {
    return "no";
  }
});

Options ​

ignoreLastCallback ​

You can pass an { ignoreLastCallback: true } as an option to this rule so that the last then() callback in a promise chain does not warn if it does not have a return. Default is false.

javascript
// OK
promise.then((x) => {
  console.log(x);
});
// OK
void promise.then((x) => {
  console.log(x);
});
// OK
await promise.then((x) => {
  console.log(x);
});

promise
  // NG
  .then((x) => {
    console.log(x);
  })
  // OK
  .then((x) => {
    console.log(x);
  });

// NG
const v = promise.then((x) => {
  console.log(x);
});
// NG
const v = await promise.then((x) => {
  console.log(x);
});
function foo() {
  // NG
  return promise.then((x) => {
    console.log(x);
  });
}

ignoreAssignmentVariable ​

You can pass an { ignoreAssignmentVariable: [] } as an option to this rule with a list of variable names so that the last then() callback in a promise chain does not warn if it does an assignment to a global variable. Default is ["globalThis"].

javascript
/* eslint promise/always-return: ["error", { ignoreAssignmentVariable: ["globalThis"] }] */

// OK
promise.then((x) => {
  globalThis = x;
});

promise.then((x) => {
  globalThis.x = x;
});

// OK
promise.then((x) => {
  globalThis.x.y = x;
});

// NG
promise.then((x) => {
  anyOtherVariable = x;
});

// NG
promise.then((x) => {
  anyOtherVariable.x = x;
});

// NG
promise.then((x) => {
  x();
});

How to use ​

To enable this rule in the CLI or using the config file, you can use:

bash
oxlint --deny promise/always-return --promise-plugin
json
{
  "plugins": ["promise"],
  "rules": {
    "promise/always-return": "error"
  }
}

References ​

Released under the MIT License.