or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basic-effects.mdchannels.mdconcurrency-effects.mdhelper-effects.mdindex.mdmiddleware.mdtesting.mdutilities.md

concurrency-effects.mddocs/

0

# Concurrency Effects

1

2

Effects for managing concurrent execution, forking tasks, and coordinating multiple asynchronous operations.

3

4

## Capabilities

5

6

### fork

7

8

Creates an effect that performs a non-blocking call on a function. Returns a Task object representing the forked execution.

9

10

```typescript { .api }

11

/**

12

* Perform non-blocking call, returns Task object

13

* @param fn - Function to fork (generator, async, or sync)

14

* @param args - Arguments to pass to the function

15

* @returns ForkEffect that resolves with Task

16

*/

17

function fork<Fn extends (...args: any[]) => any>(

18

fn: Fn,

19

...args: Parameters<Fn>

20

): ForkEffect<SagaReturnType<Fn>>;

21

22

/**

23

* Fork method on context object

24

* @param ctxAndFnName - Array of [context, methodName]

25

* @param args - Arguments to pass

26

* @returns ForkEffect

27

*/

28

function fork<Ctx extends { [P in Name]: (this: Ctx, ...args: any[]) => any }, Name extends string>(

29

ctxAndFnName: [Ctx, Name],

30

...args: Parameters<Ctx[Name]>

31

): ForkEffect<SagaReturnType<Ctx[Name]>>;

32

```

33

34

**Usage Examples:**

35

36

```typescript

37

import { fork, take, cancel } from "redux-saga/effects";

38

39

function* backgroundTask() {

40

while (true) {

41

console.log("Background work...");

42

yield delay(1000);

43

}

44

}

45

46

function* mainSaga() {

47

// Fork a background task

48

const task = yield fork(backgroundTask);

49

50

// Fork multiple tasks

51

const task1 = yield fork(fetchUser, 1);

52

const task2 = yield fork(fetchUser, 2);

53

54

// Parent waits for all forked tasks to complete

55

// before terminating (unless cancelled)

56

}

57

```

58

59

### spawn

60

61

Same as `fork()` but creates a detached task. A detached task remains independent from its parent and acts like a top-level task.

62

63

```typescript { .api }

64

/**

65

* Create detached task independent from parent

66

* @param fn - Function to spawn

67

* @param args - Arguments to pass

68

* @returns ForkEffect with detached task

69

*/

70

function spawn<Fn extends (...args: any[]) => any>(

71

fn: Fn,

72

...args: Parameters<Fn>

73

): ForkEffect<SagaReturnType<Fn>>;

74

```

75

76

**Usage Examples:**

77

78

```typescript

79

import { spawn } from "redux-saga/effects";

80

81

function* parentSaga() {

82

// Spawn detached task

83

yield spawn(independentTask);

84

85

// Parent can complete without waiting for spawned task

86

// Spawned task continues running independently

87

}

88

```

89

90

### join

91

92

Creates an effect that waits for the result of a previously forked task. If the joined task is cancelled, the cancellation propagates to the saga executing the join effect.

93

94

```typescript { .api }

95

/**

96

* Wait for result of previously forked task

97

* @param task - Task object from fork effect

98

* @returns JoinEffect that resolves with task result

99

*/

100

function join(task: Task): JoinEffect;

101

102

/**

103

* Wait for results of multiple tasks

104

* @param tasks - Array of Task objects

105

* @returns JoinEffect that resolves when all tasks complete

106

*/

107

function join(tasks: Task[]): JoinEffect;

108

```

109

110

**Usage Examples:**

111

112

```typescript

113

import { fork, join } from "redux-saga/effects";

114

115

function* coordinatorSaga() {

116

// Fork multiple tasks

117

const task1 = yield fork(fetchUser, 1);

118

const task2 = yield fork(fetchUser, 2);

119

120

// Wait for both to complete

121

const [user1, user2] = yield join([task1, task2]);

122

123

// Or join one at a time

124

const result1 = yield join(task1);

125

const result2 = yield join(task2);

126

}

127

```

128

129

### cancel

130

131

Creates an effect that cancels a previously forked task. Cancellation propagates to all child tasks and current effects.

132

133

```typescript { .api }

134

/**

135

* Cancel a previously forked task

136

* @param task - Task object to cancel

137

* @returns CancelEffect

138

*/

139

function cancel(task: Task): CancelEffect;

140

141

/**

142

* Cancel multiple tasks

143

* @param tasks - Array of tasks to cancel

144

* @returns CancelEffect

145

*/

146

function cancel(tasks: Task[]): CancelEffect;

147

148

/**

149

* Self-cancellation (cancel current task)

150

* @returns CancelEffect for self-cancellation

151

*/

152

function cancel(): CancelEffect;

153

```

154

155

**Usage Examples:**

156

157

```typescript

158

import { fork, cancel, take, cancelled } from "redux-saga/effects";

159

160

function* cancellableTask() {

161

try {

162

while (true) {

163

yield call(doWork);

164

yield delay(1000);

165

}

166

} finally {

167

if (yield cancelled()) {

168

console.log('Task was cancelled');

169

// Cleanup logic

170

}

171

}

172

}

173

174

function* controllerSaga() {

175

const task = yield fork(cancellableTask);

176

177

// Cancel on user action

178

yield take('CANCEL_BACKGROUND_TASK');

179

yield cancel(task);

180

}

181

```

182

183

### cancelled

184

185

Creates an effect that returns whether the current generator has been cancelled. Typically used in finally blocks for cleanup.

186

187

```typescript { .api }

188

/**

189

* Check if current generator has been cancelled

190

* @returns CancelledEffect that resolves with boolean

191

*/

192

function cancelled(): CancelledEffect;

193

```

194

195

### all

196

197

Creates an effect that runs multiple effects in parallel and waits for all of them to complete. Similar to `Promise.all()`.

198

199

```typescript { .api }

200

/**

201

* Run multiple effects in parallel, wait for all to complete

202

* @param effects - Array of effects to run in parallel

203

* @returns AllEffect that resolves with array of results

204

*/

205

function all<T>(effects: T[]): AllEffect<T>;

206

207

/**

208

* Run labeled effects in parallel

209

* @param effects - Object with labeled effects

210

* @returns AllEffect that resolves with object of results

211

*/

212

function all<T>(effects: { [key: string]: T }): AllEffect<T>;

213

```

214

215

**Usage Examples:**

216

217

```typescript

218

import { all, call } from "redux-saga/effects";

219

220

function* fetchAllData() {

221

// Run multiple calls in parallel (array form)

222

const [users, posts, comments] = yield all([

223

call(fetchUsers),

224

call(fetchPosts),

225

call(fetchComments)

226

]);

227

228

// Run with labels (object form)

229

const { userData, profileData } = yield all({

230

userData: call(fetchUser, userId),

231

profileData: call(fetchProfile, userId)

232

});

233

}

234

```

235

236

### race

237

238

Creates an effect that runs a race between multiple effects. The first effect to complete wins, and all others are automatically cancelled.

239

240

```typescript { .api }

241

/**

242

* Run race between multiple effects, first to complete wins

243

* @param effects - Object with labeled effects to race

244

* @returns RaceEffect that resolves with winner's result

245

*/

246

function race<T>(effects: { [key: string]: T }): RaceEffect<T>;

247

248

/**

249

* Race with array of effects

250

* @param effects - Array of effects to race

251

* @returns RaceEffect

252

*/

253

function race<T>(effects: T[]): RaceEffect<T>;

254

```

255

256

**Usage Examples:**

257

258

```typescript

259

import { race, call, take, delay } from "redux-saga/effects";

260

261

function* fetchWithTimeout() {

262

const { response, timeout } = yield race({

263

response: call(fetchUser, userId),

264

timeout: delay(5000, 'TIMEOUT')

265

});

266

267

if (timeout) {

268

console.log('Request timed out');

269

} else {

270

console.log('Got response:', response);

271

}

272

}

273

274

function* cancellableFetch() {

275

const { data, cancelled } = yield race({

276

data: call(fetchData),

277

cancelled: take('CANCEL_FETCH')

278

});

279

280

if (cancelled) {

281

console.log('Fetch was cancelled by user');

282

}

283

}

284

```

285

286

### setContext

287

288

Creates an effect that updates the saga's context. This extends the context rather than replacing it.

289

290

```typescript { .api }

291

/**

292

* Update saga's context (extends existing context)

293

* @param props - Properties to add/update in context

294

* @returns SetContextEffect

295

*/

296

function setContext<C extends object>(props: C): SetContextEffect<C>;

297

```

298

299

### getContext

300

301

Creates an effect that returns a specific property of the saga's context.

302

303

```typescript { .api }

304

/**

305

* Get property from saga's context

306

* @param prop - Property name to retrieve

307

* @returns GetContextEffect that resolves with property value

308

*/

309

function getContext(prop: string): GetContextEffect;

310

```

311

312

**Usage Examples:**

313

314

```typescript

315

import { setContext, getContext, call } from "redux-saga/effects";

316

317

function* apiSaga() {

318

// Set context

319

yield setContext({

320

apiClient: new ApiClient(),

321

userId: 123

322

});

323

324

// Get from context

325

const apiClient = yield getContext('apiClient');

326

const userId = yield getContext('userId');

327

328

const data = yield call([apiClient, 'fetchUser'], userId);

329

}

330

```

331

332

### detach

333

334

Detaches a fork effect, making it run independently of its parent.

335

336

```typescript { .api }

337

/**

338

* Detach a fork effect from its parent

339

* @param forkEffect - ForkEffect to detach

340

* @returns Detached ForkEffect

341

*/

342

function detach(forkEffect: ForkEffect): ForkEffect;

343

```

344

345

**Usage Examples:**

346

347

```typescript

348

import { fork, detach } from "redux-saga/effects";

349

350

function* parentSaga() {

351

// Create detached fork

352

yield detach(fork(backgroundService));

353

354

// Parent can complete without waiting for detached task

355

}

356

```