Φτιάξτε μια ροή συνιστωσών με το Flow.load() και εκτελέστε την με το exec()
Ένα FlowStream είναι ένα μικρό πρόγραμμα φτιαγμένο από συνιστώσες (κουτιά με εισόδους και εξόδους) και συνδέσεις μεταξύ τους. Το Total.js το εκτελεί μέσα στην εφαρμογή σας: ένα μήνυμα μπαίνει σε μια συνιστώσα, η συνιστώσα στέλνει αποτελέσματα στις εξόδους της και οι συνδέσεις τα μεταφέρουν στις επόμενες συνιστώσες. Το ίδιο σχήμα είναι αυτό που σχεδιάζει ο σχεδιαστής Flow του Total.js· εδώ είναι γραμμένο με το χέρι.
Το Flow.load(schema, [callback]) ξεκινά ένα FlowStream και δίνει στο callback (err, instance). Το σχήμα είναι ένα αντικείμενο:
idκαιname: το id είναι το κλειδί στοFlow.instances(Flow.instances.demo)· χωρίς id δημιουργείται ένα τυχαίο.components: ένα αντικείμενο με τον πηγαίο κώδικα κάθε συνιστώσας, ως κείμενο. Το κείμενο είναι ένα σενάριο,<script total>...</script>(η μορφή που αποθηκεύει ο σχεδιαστής).design: οι περιπτώσεις των συνιστωσών. Καθεμία έχει έναid, τοcomponentπου χρησιμοποιεί, τοconfigτης καιconnections, ένα αντικείμενο του οποίου τα κλειδιά είναι id εξόδων και οι τιμές είναι λίστες{ id, index }: η περίπτωση και το id εισόδου που λαμβάνουν ό,τι στέλνεται σε αυτή την έξοδο.variables: τιμές που μπορούν να διαβάσουν οι συνιστώσες.
Μια συνιστώσα είναι μια ενότητα: exports.id, exports.name, exports.inputs και exports.outputs (λίστες { id, name }), exports.config (οι προεπιλογές) και exports.make = function(instance, config). Στο make() η συνιστώσα ορίζει το instance.message = function($) {}, που λαμβάνει κάθε μήνυμα: το $.data είναι τα δεδομένα, το $.send(outputid, data) τα στέλνει σε μια έξοδο και το $.destroy() τελειώνει ένα μήνυμα που δεν πάει παρακάτω.
Για να χρησιμοποιήσετε τη ροή από τον κώδικά σας, το instance.exec({ id, data, callback }) στέλνει το data στην περίπτωση id και καλεί το callback(err, message) όταν το μήνυμα τελειώσει· το τελευταίο μήνυμα της αλυσίδας είναι το message (άρα το message.data είναι αυτό που έλαβε η τελευταία συνιστώσα). Το instance.reconfigure(id, config) αλλάζει τη ρύθμιση μιας περίπτωσης που τρέχει και το Flow.remove(id) σταματά το FlowStream και το ξεχνά. Το FlowStream είναι το ίδιο αντικείμενο με το Flow: δύο ονόματα για τον διαχειριστή.
Μια συνιστώσα είναι κώδικας που τρέχει με όλα τα δικαιώματα της εφαρμογής (στο ίδιο νήμα εκτός αν το σχήμα λέει worker). Μη φορτώνετε ποτέ σχήμα ή συνιστώσα που μπορεί να γράψει ένας επισκέπτης.
const upper = `<script total>
exports.id = 'upper';
exports.name = 'Upper case';
exports.inputs = [{ id: 'input', name: 'Input' }];
exports.outputs = [{ id: 'output', name: 'Output' }];
exports.config = { prefix: '' };
exports.make = function(instance, config) {
instance.message = function($) {
$.send('output', config.prefix + String($.data).toUpperCase());
};
};
</script>`;
const collect = `<script total>
exports.id = 'collect';
exports.name = 'Collect';
exports.inputs = [{ id: 'input', name: 'Input' }];
exports.make = function(instance) {
instance.message = function($) {
MAIN.collected.push($.data);
$.destroy();
};
};
</script>`;
MAIN.collected = [];
MAIN.flow = null;
Flow.load({
id: 'demo',
name: 'Demo',
components: { upper: upper, collect: collect },
design: {
a: { id: 'a', component: 'upper', config: { prefix: '> ' }, connections: { output: [{ id: 'b', index: 'input' }] } },
b: { id: 'b', component: 'collect', config: {}, connections: {} }
},
variables: {}
}, function(err, instance) {
MAIN.flow = instance;
});exports.install = function() {
ROUTE('GET /shout/', shout);
ROUTE('POST /prefix/ @json', prefix);
ROUTE('GET /collected/', collected);
ROUTE('GET /info/', info);
ROUTE('POST /stop/', stop);
};
function shout($) {
if (!MAIN.flow)
return $.invalid('The flow is not running');
MAIN.flow.exec({ id: 'a', data: $.query.text, callback: (err, message) => $.json({ result: message ? message.data : null }) });
}
function prefix($) {
MAIN.flow.reconfigure('a', { prefix: $.body.prefix });
$.json({ ok: true });
}
function collected($) {
$.json(MAIN.collected);
}
function info($) {
$.json({ flows: Object.keys(Flow.instances), instances: Object.keys(MAIN.flow.flow.meta.flow), same: Flow === FlowStream });
}
function stop($) {
Flow.remove('demo');
MAIN.flow = null;
$.json({ flows: Object.keys(Flow.instances) });
}