or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdjson-utilities.mdmime-data.mdpromise-delegation.mdrandom-generation.mdtoken-system.mduuid-generation.md

promise-delegation.mddocs/

0

# Promise Delegation

1

2

Promise wrapper that separates promise creation from resolution logic, enabling flexible asynchronous workflows where the resolution logic cannot be defined at the point of promise creation.

3

4

## Capabilities

5

6

### PromiseDelegate Class

7

8

A class which wraps a promise into a delegate object, allowing external resolution or rejection of the promise.

9

10

```typescript { .api }

11

/**

12

* A class which wraps a promise into a delegate object.

13

*

14

* Notes:

15

* This class is useful when the logic to resolve or reject a promise

16

* cannot be defined at the point where the promise is created.

17

*/

18

class PromiseDelegate<T> {

19

/**

20

* Construct a new promise delegate

21

*/

22

constructor();

23

24

/**

25

* The promise wrapped by the delegate

26

*/

27

readonly promise: Promise<T>;

28

29

/**

30

* Resolve the wrapped promise with the given value

31

* @param value - The value to use for resolving the promise

32

*/

33

resolve(value: T | PromiseLike<T>): void;

34

35

/**

36

* Reject the wrapped promise with the given value

37

* @param reason - The reason for rejecting the promise

38

*/

39

reject(reason: any): void;

40

}

41

```

42

43

**Usage Examples:**

44

45

```typescript

46

import { PromiseDelegate } from "@lumino/coreutils";

47

48

// Basic usage - create a delegate and resolve it later

49

const delegate = new PromiseDelegate<string>();

50

51

// The promise can be awaited or chained

52

delegate.promise.then(value => {

53

console.log("Resolved with:", value);

54

}).catch(error => {

55

console.log("Rejected with:", error);

56

});

57

58

// Later, resolve the promise from elsewhere

59

setTimeout(() => {

60

delegate.resolve("Hello, World!");

61

}, 1000);

62

63

// Or reject it

64

// delegate.reject(new Error("Something went wrong"));

65

```

66

67

### Common Use Cases

68

69

**Async Event Handling:**

70

71

```typescript

72

import { PromiseDelegate } from "@lumino/coreutils";

73

74

class EventEmitter {

75

private listeners = new Map<string, PromiseDelegate<any>[]>();

76

77

// Wait for a specific event to occur

78

waitForEvent<T>(eventName: string): Promise<T> {

79

const delegate = new PromiseDelegate<T>();

80

81

if (!this.listeners.has(eventName)) {

82

this.listeners.set(eventName, []);

83

}

84

this.listeners.get(eventName)!.push(delegate);

85

86

return delegate.promise;

87

}

88

89

// Emit an event, resolving all waiting promises

90

emit<T>(eventName: string, data: T): void {

91

const delegates = this.listeners.get(eventName) || [];

92

delegates.forEach(delegate => delegate.resolve(data));

93

this.listeners.set(eventName, []);

94

}

95

}

96

97

// Usage

98

const emitter = new EventEmitter();

99

const dataPromise = emitter.waitForEvent<{id: number, name: string}>("user-loaded");

100

101

dataPromise.then(userData => {

102

console.log("User loaded:", userData.name);

103

});

104

105

// Later, in another part of the application

106

emitter.emit("user-loaded", { id: 123, name: "Alice" });

107

```

108

109

**Resource Loading:**

110

111

```typescript

112

import { PromiseDelegate } from "@lumino/coreutils";

113

114

class ResourceLoader {

115

private loadingPromises = new Map<string, PromiseDelegate<any>>();

116

117

loadResource<T>(url: string): Promise<T> {

118

// Return existing promise if already loading

119

if (this.loadingPromises.has(url)) {

120

return this.loadingPromises.get(url)!.promise;

121

}

122

123

// Create new delegate for this resource

124

const delegate = new PromiseDelegate<T>();

125

this.loadingPromises.set(url, delegate);

126

127

// Start loading (could be HTTP request, file read, etc.)

128

this.startLoading(url, delegate);

129

130

return delegate.promise;

131

}

132

133

private startLoading<T>(url: string, delegate: PromiseDelegate<T>): void {

134

// Simulate async loading

135

fetch(url)

136

.then(response => response.json())

137

.then(data => {

138

delegate.resolve(data);

139

this.loadingPromises.delete(url);

140

})

141

.catch(error => {

142

delegate.reject(error);

143

this.loadingPromises.delete(url);

144

});

145

}

146

}

147

148

// Usage

149

const loader = new ResourceLoader();

150

const userPromise = loader.loadResource<{name: string, email: string}>("/api/user/123");

151

const configPromise = loader.loadResource<{theme: string, locale: string}>("/api/config");

152

153

Promise.all([userPromise, configPromise]).then(([user, config]) => {

154

console.log(`Hello ${user.name}, your theme is ${config.theme}`);

155

});

156

```

157

158

**Conditional Resolution:**

159

160

```typescript

161

import { PromiseDelegate } from "@lumino/coreutils";

162

163

class ConditionalTask<T> {

164

private delegate = new PromiseDelegate<T>();

165

private conditions: (() => boolean)[] = [];

166

167

constructor() {}

168

169

get promise(): Promise<T> {

170

return this.delegate.promise;

171

}

172

173

addCondition(condition: () => boolean): this {

174

this.conditions.push(condition);

175

this.checkConditions();

176

return this;

177

}

178

179

setResult(result: T): void {

180

this.result = result;

181

this.checkConditions();

182

}

183

184

setError(error: any): void {

185

this.delegate.reject(error);

186

}

187

188

private result?: T;

189

190

private checkConditions(): void {

191

if (this.result !== undefined && this.conditions.every(cond => cond())) {

192

this.delegate.resolve(this.result);

193

}

194

}

195

}

196

197

// Usage

198

const task = new ConditionalTask<string>();

199

200

let userLoggedIn = false;

201

let dataLoaded = false;

202

203

task

204

.addCondition(() => userLoggedIn)

205

.addCondition(() => dataLoaded);

206

207

task.promise.then(result => {

208

console.log("All conditions met:", result);

209

});

210

211

// Simulate conditions being met

212

setTimeout(() => {

213

userLoggedIn = true;

214

task.setResult("Task completed!");

215

}, 1000);

216

217

setTimeout(() => {

218

dataLoaded = true;

219

}, 1500);

220

```

221

222

**Timeout with Cleanup:**

223

224

```typescript

225

import { PromiseDelegate } from "@lumino/coreutils";

226

227

function withTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T> {

228

const delegate = new PromiseDelegate<T>();

229

let timeoutId: number;

230

231

// Race between the original promise and timeout

232

promise.then(

233

value => {

234

clearTimeout(timeoutId);

235

delegate.resolve(value);

236

},

237

error => {

238

clearTimeout(timeoutId);

239

delegate.reject(error);

240

}

241

);

242

243

timeoutId = setTimeout(() => {

244

delegate.reject(new Error(`Operation timed out after ${timeoutMs}ms`));

245

}, timeoutMs);

246

247

return delegate.promise;

248

}

249

250

// Usage

251

const slowOperation = new Promise(resolve => {

252

setTimeout(() => resolve("Done!"), 5000);

253

});

254

255

const fastTimeout = withTimeout(slowOperation, 2000);

256

257

fastTimeout.catch(error => {

258

console.log(error.message); // "Operation timed out after 2000ms"

259

});

260

```