# promise/no-callback-in-promise

> Disallow calling a callback inside `then()` or `catch()`

If a callback throws while it runs inside `then()` or `catch()`, the error doesn't reach the caller. The promise turns it into a rejection. In the example below, if `callback` throws in the `then()`, the `catch()` calls it a second time with that error.

A callback is a function named `callback`, `cb`, `done` or `next`. Inside a function passed to `then()` or `catch()`, the rule reports calling one, and passing one as the first argument to another call. It also reports `.then(callback)` and `.catch(callback)`.

A callback scheduled with `setImmediate`, `setTimeout`, `requestAnimationFrame` or `nextTick` runs after the promise handler has returned, so it isn't reported.

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"promise/no-callback-in-promise" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"promise/no-callback-in-promise" = ["error", {
  exceptions = [], # list of strings
  timeoutsErr = false,
}]
```

## Examples

Reported:

```js
function getUser(id, callback) {
  fetchUser(id)
    .then(user => callback(null, user))
    .catch(callback);
}
```

```js
fetchUser(id).then(user => finish(done, user));
```

Not reported:

```js
function getUser(id, callback) {
  fetchUser(id)
    .then(user => setImmediate(callback, null, user))
    .catch(err => setImmediate(() => callback(err)));
}
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `exceptions` | `[]` | Names from the list above that aren't callbacks in your code. |
| `timeoutsErr` | `false` | Also report callbacks scheduled with `setImmediate`, `setTimeout`, `requestAnimationFrame` or `nextTick`. |

```js
app.get("/users/:id", (req, res, next) => {
  fetchUser(req.params.id)
    .then(user => res.json(user))
    .catch(next);
});
```

```js
function getUser(id, callback) {
  fetchUser(id).then(user => setImmediate(callback, null, user));
}
```
