mirror of
https://github.com/HeyPuter/puter.git
synced 2025-02-02 23:28:39 +08:00
dev: add Invoker
This commit is contained in:
parent
9e38e048c1
commit
20b58ddcb5
53
src/puter-js-common/src/libs/invoker.js
Normal file
53
src/puter-js-common/src/libs/invoker.js
Normal file
@ -0,0 +1,53 @@
|
||||
const { AdvancedBase } = require("../..");
|
||||
|
||||
class Invoker extends AdvancedBase {
|
||||
static create ({
|
||||
decorators,
|
||||
delegate,
|
||||
}) {
|
||||
const invoker = new Invoker();
|
||||
invoker.decorators = decorators;
|
||||
invoker.delegate = delegate;
|
||||
return invoker;
|
||||
}
|
||||
async run (args) {
|
||||
let fn = this.delegate;
|
||||
const decorators = this.decorators;
|
||||
for ( let i = decorators.length-1 ; i >= 0 ; i-- ) {
|
||||
const dec = decorators[i];
|
||||
fn = this.add_dec_(dec, fn);
|
||||
}
|
||||
return await fn(args);
|
||||
}
|
||||
add_dec_ (dec, fn) {
|
||||
return async (args) => {
|
||||
try {
|
||||
if ( dec.on_call ) {
|
||||
args = await dec.on_call(args);
|
||||
}
|
||||
let result = await fn(args);
|
||||
if ( dec.on_return ) {
|
||||
result = await dec.on_return(result);
|
||||
}
|
||||
return result;
|
||||
} catch (e) {
|
||||
if ( ! dec.on_error ) throw e;
|
||||
|
||||
let cancel = false;
|
||||
const a = {
|
||||
error () { return e },
|
||||
cancel_error () { cancel = true; },
|
||||
};
|
||||
const result = await dec.on_error(a);
|
||||
if ( cancel ) {
|
||||
return result;
|
||||
}
|
||||
throw result ?? e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Invoker,
|
||||
};
|
@ -19,6 +19,7 @@
|
||||
const { expect } = require('chai');
|
||||
const { BasicBase } = require('../src/bases/BasicBase');
|
||||
const { AdvancedBase } = require('../src/AdvancedBase');
|
||||
const { Invoker } = require('../src/libs/invoker');
|
||||
|
||||
class ClassA extends BasicBase {
|
||||
static STATIC_OBJ = {
|
||||
@ -70,3 +71,40 @@ describe('AdvancedBase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('lib:invoker', () => {
|
||||
it('works', async () => {
|
||||
const invoker = Invoker.create({
|
||||
decorators: [
|
||||
{
|
||||
name: 'uphill both ways',
|
||||
on_call: (args) => {
|
||||
return {
|
||||
...args,
|
||||
n: args.n + 1,
|
||||
};
|
||||
},
|
||||
on_return: (result) => {
|
||||
return {
|
||||
n: result.n + 1,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'error number five',
|
||||
on_error: a => {
|
||||
a.cancel_error();
|
||||
return { n: 5 };
|
||||
},
|
||||
}
|
||||
],
|
||||
async delegate (args) {
|
||||
const { n } = args;
|
||||
if ( n === 3 ) {
|
||||
throw new Error('test error');
|
||||
}
|
||||
return { n: 'oops' };
|
||||
}
|
||||
});
|
||||
expect(await invoker.run({ n: 2 })).to.deep.equal({ n: 6 });
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user