Skip to content

Commit

Permalink
feat(example-context): add an example to demonstrate ValueOrPromise
Browse files Browse the repository at this point in the history
  • Loading branch information
raymondfeng committed Jun 3, 2019
1 parent 01383b7 commit 0f143ed
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 8 deletions.
1 change: 1 addition & 0 deletions examples/context/README.md
Expand Up @@ -21,6 +21,7 @@ Control (IoC) and Dependency Injection (DI) capabilities provided by
| [interceptor-proxy.ts](https://github.com/strongloop/loopback-next/blob/master/examples/context/src/interceptor-proxy.ts) | Get proxies to intercept method invocations |
| [parameterized-decoration.ts](https://github.com/strongloop/loopback-next/blob/master/examples/context/src/parameterized-decoration.ts) | Apply decorators that require parameters as arguments |
| [sync-async.ts](https://github.com/strongloop/loopback-next/blob/master/examples/context/src/sync-async.ts) | Resolve bindings with dependencies synchronously or asynchronously |
| [value-promise.ts](https://github.com/strongloop/loopback-next/blob/master/examples/context/src/value-promise.ts) | Handle synchronous or asynchronous results (ValueOrPromise) |

## Use

Expand Down
22 changes: 14 additions & 8 deletions examples/context/fixtures/examples-output.txt
@@ -1,9 +1,9 @@
> binding-types.js
[2019-06-01T22:49:33.602Z] (/greet#1) Hello, John
[2019-06-01T22:49:33.621Z] (/greet#2) Hello, John
[2019-06-02T06:50:02.765Z] (/greet#1) Hello, John
[2019-06-02T06:50:02.766Z] (/greet#2) Hello, John

> configuration-injection.js
[2019-06-01T22:49:33.641Z] >>>: Hello, Ray
[2019-06-02T06:50:02.768Z] >>>: Hello, Ray

> context-chain.js
[app] Hello, John!
Expand Down Expand Up @@ -35,13 +35,13 @@ Context: invocation-context Binding: greeter
Injection: Greeter.constructor[0]
Context: invocation-context Binding: greeter
Injection: Greeter.prototype.prefix
[2019-06-01T22:49:33.650Z] Hello, John
[2019-06-02T06:50:02.777Z] Hello, John

> dependency-injection.js
[2019-06-01T22:49:33.652Z] (en) Hello, Jane!
[2019-06-01T22:49:33.653Z] Hello, John!
[2019-06-01T22:49:33.653Z] (zh) 你好,John!
[2019-06-01T22:49:33.653Z] (en) Hello, Jane!
[2019-06-02T06:50:02.778Z] (en) Hello, Jane!
[2019-06-02T06:50:02.779Z] Hello, John!
[2019-06-02T06:50:02.779Z] (zh) 你好,John!
[2019-06-02T06:50:02.780Z] (en) Hello, Jane!

> find-bindings.js
greeters.EnglishGreeter
Expand Down Expand Up @@ -72,3 +72,9 @@ Hello, John (sync)
Hello, Jane (async)
Expect to fail with error: Cannot get greeter synchronously: the value is a promise

> value-promise.js
sync: [ '[value] Hello, John!', '[value] 你好,John!' ]
{ en: '[value] Hello, Jane!', zh: '[value] 你好,Jane!' }
async: [ '[value] Hello, John!', '[promise] 你好,John!' ]
{ en: '[value] Hello, Jane!', zh: '[promise] 你好,Jane!' }

104 changes: 104 additions & 0 deletions examples/context/src/value-promise.ts
@@ -0,0 +1,104 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/example-context
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {
Context,
ContextView,
filterByTag,
isPromiseLike,
resolveList,
resolveMap,
transformValueOrPromise,
ValueOrPromise,
} from '@loopback/context';

/**
* A greeter
*/
interface Greeter {
language: string;
/**
* Greet in the given language
* @param name - Name
* @returns A message or a promise of a message
*/
greet(name: string): ValueOrPromise<string>;
}

class ChineseGreeter implements Greeter {
language = 'zh';
greet(name: string) {
return `[value] 你好,${name}!`;
}
}

class EnglishGreeter implements Greeter {
language = 'en';
greet(name: string) {
return `[value] Hello, ${name}!`;
}
}

class AsyncChineseGreeter implements Greeter {
language = 'zh';
greet(name: string) {
return new Promise<string>(resolve =>
setImmediate(() => {
resolve(`[promise] 你好,${name}!`);
}),
);
}
}

export async function main() {
const ctx = new Context('app');

// Add EnglishGreeter for now
ctx
.bind('greeters.EnglishGreeter')
.toClass(EnglishGreeter)
.tag('greeter');

// Add ChineseGreeter
ctx
.bind('greeters.ChineseGreeter')
.toClass(ChineseGreeter)
.tag('greeter');

const greetersView = ctx.createView<Greeter>(filterByTag('greeter'));
await greetFromAll(greetersView);

// Replace ChineseGreeter with AsyncChineseGreeter
ctx
.bind('greeters.ChineseGreeter')
.toClass(AsyncChineseGreeter)
.tag('greeter');

await greetFromAll(greetersView);
}

async function greetFromAll(greetersView: ContextView<Greeter>) {
const greeters = await greetersView.values();
const greetings = resolveList(greeters, greeter => {
return greeter.greet('John');
});
if (isPromiseLike(greetings)) {
console.log('async:', await greetings);
} else {
console.log('sync:', greetings);
}
const greeterMap: {
[language: string]: Greeter;
} = {};
greeters.filter(greeter => (greeterMap[greeter.language] = greeter));
const greetingsByLanguage = resolveMap(greeterMap, greeter =>
greeter.greet('Jane'),
);

await transformValueOrPromise(greetingsByLanguage, console.log);
}

// tslint:disable-next-line:no-floating-promises
if (require.main === module) main();

0 comments on commit 0f143ed

Please sign in to comment.