Skip to content

Commit 601ecbf

Browse files
committed
refactor: add helper methods to do work with binding/injection
1 parent e6dc4a4 commit 601ecbf

File tree

3 files changed

+105
-54
lines changed

3 files changed

+105
-54
lines changed

packages/context/src/binding.ts

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -254,28 +254,11 @@ export class Binding {
254254
}
255255
}
256256
if (this._getValue) {
257-
const resolutionSession = ResolutionSession.enterBinding(this, session);
258-
let result: ValueOrPromise<BoundValue>;
259-
try {
260-
result = this._getValue(ctx, resolutionSession);
261-
} catch (e) {
262-
resolutionSession.popBinding();
263-
throw e;
264-
}
265-
if (isPromise(result)) {
266-
result = result.then(
267-
(val: BoundValue) => {
268-
resolutionSession.popBinding();
269-
return val;
270-
},
271-
err => {
272-
resolutionSession.popBinding();
273-
throw err;
274-
},
275-
);
276-
} else {
277-
resolutionSession.popBinding();
278-
}
257+
let result = ResolutionSession.runWithBinding(
258+
s => this._getValue(ctx, s),
259+
this,
260+
session,
261+
);
279262
return this._cacheValue(ctx, result);
280263
}
281264
return Promise.reject(

packages/context/src/resolution-session.ts

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,22 @@
33
// This file is licensed under the MIT License.
44
// License text available at https://opensource.org/licenses/MIT
55

6-
import {Binding} from './binding';
6+
import {Binding, ValueOrPromise, BoundValue} from './binding';
77
import {Injection} from './inject';
8+
import {isPromise} from './is-promise';
89
import * as debugModule from 'debug';
910
import {DecoratorFactory} from '@loopback/metadata';
1011

1112
const debugSession = debugModule('loopback:context:resolver:session');
1213
const getTargetName = DecoratorFactory.getTargetName;
14+
15+
/**
16+
* A function to be executed with the resolution session
17+
*/
18+
export type ResolutionAction = (
19+
session?: ResolutionSession,
20+
) => ValueOrPromise<BoundValue>;
21+
1322
/**
1423
* Object to keep states for a session to resolve bindings and their
1524
* dependencies within a context
@@ -42,7 +51,7 @@ export class ResolutionSession {
4251
* @param binding Binding
4352
* @param session Resolution session
4453
*/
45-
static enterBinding(
54+
private static enterBinding(
4655
binding: Binding,
4756
session?: ResolutionSession,
4857
): ResolutionSession {
@@ -51,12 +60,48 @@ export class ResolutionSession {
5160
return session;
5261
}
5362

63+
/**
64+
* Run the given action with the given binding and session
65+
* @param action A function to do some work with the resolution session
66+
* @param binding The current binding
67+
* @param session The current resolution session
68+
*/
69+
static runWithBinding(
70+
action: ResolutionAction,
71+
binding: Binding,
72+
session?: ResolutionSession,
73+
) {
74+
const resolutionSession = ResolutionSession.enterBinding(binding, session);
75+
let result: ValueOrPromise<BoundValue>;
76+
try {
77+
result = action(resolutionSession);
78+
} catch (e) {
79+
resolutionSession.popBinding();
80+
throw e;
81+
}
82+
if (isPromise(result)) {
83+
result = result.then(
84+
val => {
85+
resolutionSession.popBinding();
86+
return val;
87+
},
88+
err => {
89+
resolutionSession.popBinding();
90+
throw err;
91+
},
92+
);
93+
} else {
94+
resolutionSession.popBinding();
95+
}
96+
return result;
97+
}
98+
5499
/**
55100
* Push an injection into the session
56101
* @param injection Injection
57102
* @param session Resolution session
58103
*/
59-
static enterInjection(
104+
private static enterInjection(
60105
injection: Injection,
61106
session?: ResolutionSession,
62107
): ResolutionSession {
@@ -65,6 +110,45 @@ export class ResolutionSession {
65110
return session;
66111
}
67112

113+
/**
114+
* Run the given action with the given injection and session
115+
* @param action A function to do some work with the resolution session
116+
* @param binding The current injection
117+
* @param session The current resolution session
118+
*/
119+
static runWithInjection(
120+
action: ResolutionAction,
121+
injection: Injection,
122+
session?: ResolutionSession,
123+
) {
124+
const resolutionSession = ResolutionSession.enterInjection(
125+
injection,
126+
session,
127+
);
128+
let result: ValueOrPromise<BoundValue>;
129+
try {
130+
result = action(resolutionSession);
131+
} catch (e) {
132+
resolutionSession.popInjection();
133+
throw e;
134+
}
135+
if (isPromise(result)) {
136+
result = result.then(
137+
val => {
138+
resolutionSession.popInjection();
139+
return val;
140+
},
141+
err => {
142+
resolutionSession.popInjection();
143+
throw err;
144+
},
145+
);
146+
} else {
147+
resolutionSession.popInjection();
148+
}
149+
return result;
150+
}
151+
68152
/**
69153
* Describe the injection for debugging purpose
70154
* @param injection

packages/context/src/resolver.ts

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -121,35 +121,19 @@ function resolve<T>(
121121
ResolutionSession.describeInjection(injection),
122122
);
123123
}
124-
let resolved: ValueOrPromise<T>;
125-
// Push the injection onto the session
126-
session = ResolutionSession.enterInjection(injection, session);
127-
try {
128-
if (injection.resolve) {
129-
// A custom resolve function is provided
130-
resolved = injection.resolve(ctx, injection, session);
131-
} else {
132-
// Default to resolve the value from the context by binding key
133-
resolved = ctx.getValueOrPromise(injection.bindingKey, session);
134-
}
135-
} catch (e) {
136-
session.popBinding();
137-
throw e;
138-
}
139-
if (isPromise(resolved)) {
140-
resolved = resolved.then(
141-
r => {
142-
session!.popInjection();
143-
return r;
144-
},
145-
e => {
146-
session!.popInjection();
147-
throw e;
148-
},
149-
);
150-
} else {
151-
session.popInjection();
152-
}
124+
let resolved = ResolutionSession.runWithInjection(
125+
s => {
126+
if (injection.resolve) {
127+
// A custom resolve function is provided
128+
return injection.resolve(ctx, injection, s);
129+
} else {
130+
// Default to resolve the value from the context by binding key
131+
return ctx.getValueOrPromise(injection.bindingKey, s);
132+
}
133+
},
134+
injection,
135+
session,
136+
);
153137
return resolved;
154138
}
155139

0 commit comments

Comments
 (0)