You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-07-31 05:44:24 +03:00
RESP3 Support - Some commands responses in RESP3 aren't stable yet and therefore return an "untyped" ReplyUnion. Sentinel TypeMapping Correctly types Multi commands Note: some API changes to be further documented in v4-to-v5.md
54 lines
2.1 KiB
Markdown
54 lines
2.1 KiB
Markdown
# [Transactions](https://redis.io/docs/interact/transactions/) ([`MULTI`](https://redis.io/commands/multi/)/[`EXEC`](https://redis.io/commands/exec/))
|
|
|
|
Start a [transaction](https://redis.io/docs/interact/transactions/) by calling `.multi()`, then chaining your commands. When you're done, call `.exec()` and you'll get an array back with your results:
|
|
|
|
```javascript
|
|
const [setReply, getReply] = await client.multi()
|
|
.set('key', 'value')
|
|
.get('another-key')
|
|
.exec();
|
|
```
|
|
|
|
## `exec<'typed'>()`/`execTyped()`
|
|
|
|
A transaction invoked with `.exec<'typed'>`/`execTyped()` will return types appropriate to the commands in the transaction:
|
|
|
|
```javascript
|
|
const multi = client.multi().ping();
|
|
await multi.exec(); // Array<ReplyUnion>
|
|
await multi.exec<'typed'>(); // [string]
|
|
await multi.execTyped(); // [string]
|
|
```
|
|
|
|
> :warning: this only works when all the commands are invoked in a single "call chain"
|
|
|
|
## [`WATCH`](https://redis.io/commands/watch/)
|
|
|
|
You can also [watch](https://redis.io/docs/interact/transactions/#optimistic-locking-using-check-and-set) keys by calling `.watch()`. Your transaction will abort if any of the watched keys change or if the client reconnected between the `watch` and `exec` calls.
|
|
|
|
The `WATCH` state is stored on the connection (by the server). In case you need to run multiple `WATCH` & `MULTI` in parallel you'll need to use a [pool](./pool.md).
|
|
|
|
## `execAsPipeline`
|
|
|
|
`execAsPipeline` will execute the commands without "wrapping" it with `MULTI` & `EXEC` (and lose the transactional semantics).
|
|
|
|
```javascript
|
|
await client.multi()
|
|
.get('a')
|
|
.get('b')
|
|
.execAsPipeline();
|
|
```
|
|
|
|
the diffrence between the above pipeline and `Promise.all`:
|
|
|
|
```javascript
|
|
await Promise.all([
|
|
client.get('a'),
|
|
client.get('b')
|
|
]);
|
|
```
|
|
|
|
is that if the socket disconnects during the pipeline, any unwritten commands will be discarded. i.e. if the socket disconnects after `GET a` is written to the socket, but before `GET b` is:
|
|
- using `Promise.all` - the client will try to execute `GET b` when the socket reconnects
|
|
- using `execAsPipeline` - `GET b` promise will be rejected as well
|