1 | // Import
|
2 | import { isError } from 'https://unpkg.com/typechecker@^7.17.0/edition-deno/index.ts'
|
3 |
|
4 | // Handle success case
|
5 | function onSuccess(value: any) {
|
6 | // Reject if an error was returned
|
7 | if (isError(value)) return Promise.reject(value)
|
8 | // Success case, so return the value
|
9 | return value
|
10 | }
|
11 |
|
12 | /**
|
13 | * Ambidextrously execute the method with the passed arguments.
|
14 | * If method.length > args.length, then ambi provides the method with a completion callback as the last expected argument.
|
15 | * @param method A method, that can either resolve synchronously, via a promise, or via a callback.
|
16 | * @param args The arguments to provide the function.
|
17 | * @returns The determined result.
|
18 | */
|
19 | export default function ambi<Result>(
|
20 | method: Function,
|
21 | ...args: any
|
22 | ): Promise<Result> {
|
23 | /*
|
24 | Different ways functions can be called:
|
25 | ambi(function(a,next){next(null, a)}, a)
|
26 | > method.length > args.length
|
27 | > next will be provided automatically
|
28 | ambi(function(a){return a}, a)
|
29 | > method.length = args.length
|
30 | > no argument changes by ambi
|
31 | ambi(function(a){return a}, a, b)
|
32 | > method.length < args.length
|
33 | > no argument changes by ambi
|
34 | */
|
35 | try {
|
36 | // Inject a completion callback
|
37 | if (method.length > args.length) {
|
38 | return new Promise(function (resolve, reject) {
|
39 | const xargs = args
|
40 | .slice()
|
41 | // add the difference as undefined values
|
42 | .concat(new Array(method.length - args.length - 1))
|
43 | // add the completion callback
|
44 | .concat([
|
45 | function ambiCallback(err?: Error, ...args: any) {
|
46 | if (err) return reject(err)
|
47 | if (args.length === 1) return resolve(args[0])
|
48 | return resolve(args)
|
49 | },
|
50 | ])
|
51 | method(...xargs)
|
52 | }).then(onSuccess)
|
53 | }
|
54 | // Execute without a completion callback
|
55 | else {
|
56 | return Promise.resolve(method(...args)).then(onSuccess)
|
57 | }
|
58 | } catch (err) {
|
59 | return Promise.reject(err)
|
60 | }
|
61 | }
|