ESLint Plugin for Promises
eslint-plugin-promise is an ESLint plugin designed to enforce best practices and prevent common pitfalls when working with JavaScript Promises. It ensures proper promise chain construction, error handling, and discourages anti-patterns like callbacks inside `then()` blocks. The current stable version is `7.2.1`, released in November 2024, indicating an active development and maintenance cadence with several releases throughout the year addressing bugs and adding features. Key differentiators include its comprehensive set of rules covering various promise use cases, from enforcing `catch()` or `return` to disallowing multiple resolutions and improper nesting, thereby enhancing code readability and reliability in asynchronous operations. It supports both legacy `.eslintrc.*` configurations and modern ESLint flat configurations.
Common errors
-
Error: Failed to load plugin 'promise' declared in '.eslintrc.js': Cannot find module 'eslint-plugin-promise'
cause The eslint-plugin-promise package was not installed or not installed correctly in the project.fixRun `npm install eslint-plugin-promise --save-dev` or `yarn add eslint-plugin-promise --dev`. -
ESLint couldn't find the plugin "promise". (While processing 'eslint.config.js')
cause In ESLint's flat configuration, plugins must be explicitly imported and then mapped in the `plugins` object within your configuration.fixEnsure `import pluginPromise from 'eslint-plugin-promise';` is at the top of `eslint.config.js`, and the plugin is mapped in `plugins: { promise: pluginPromise }`. -
Definition for rule 'promise/always-return' was not found.
cause The plugin is loaded, but ESLint cannot find the specified rule. This often happens if the plugin is not correctly associated with its rules.fixVerify that `plugins: { promise: pluginPromise }` is correctly defined in your flat config, or that `"plugins": ["promise"]` is in your `.eslintrc.*` and that the rule name is correctly prefixed (`promise/`).
Warnings
- breaking Version 7.0.0 updated Node.js and ESLint peer dependency versions to align with ESLint v9, which means Node.js versions prior to 18.18.0 and ESLint versions older than 7.0.0 are no longer officially supported.
- gotcha The `prefer-await-to-then` rule, when used with the `strict` option, will disallow `.then()` or `.catch()` following `await` expressions, which can be useful for enforcing full `async/await` syntax but might break existing codebases using mixed patterns.
- gotcha The `no-callback-in-promise` rule can sometimes trigger false positives, especially in complex scenarios or when using specific patterns that mimic callbacks but are not true anti-patterns for promises.
- breaking With the introduction of ESLint's flat configuration system (ESLint v9+), the way plugins are configured has changed. The `extends` property with `plugin:promise/recommended` in `.eslintrc.*` is for legacy configurations.
Install
-
npm install eslint-plugin-promise -
yarn add eslint-plugin-promise -
pnpm add eslint-plugin-promise
Imports
- ESLint Flat Config
import pluginPromise from 'eslint-plugin-promise';
- Legacy .eslintrc Configuration
import { rules } from 'eslint-plugin-promise'{ "plugins": ["promise"] } - Recommended Ruleset (Legacy)
{ "extends": ["plugin:promise/recommended"] } - Recommended Ruleset (Flat Config)
pluginPromise.configs['flat/recommended']
Quickstart
import pluginPromise from 'eslint-plugin-promise';
import globals from 'globals';
export default [
{
files: ['**/*.js'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
...globals.node,
...globals.browser
}
},
plugins: {
promise: pluginPromise
},
rules: {
...pluginPromise.configs['flat/recommended'].rules,
// Override or add specific rules
'promise/always-return': 'error',
'promise/no-nesting': 'warn',
'promise/prefer-await-to-then': 'error'
}
}
];
// Example file: src/async.js
// async function fetchData() {
// return fetch('/api/data')
// .then(response => response.json())
// .catch(error => console.error('Fetch error:', error));
// }
//
// const badPromise = new Promise(resolve => {
// resolve('first');
// resolve('second'); // Will be flagged by no-multiple-resolved
// });
//
// function processData(data, cb) {
// Promise.resolve(data).then(() => {
// cb(null, data); // Will be flagged by no-callback-in-promise
// });
// }
//
// fetchData();