ForgeTotal.js 5
el

Total.js 5

Φτιάξτε μια ροή συνιστωσών με το Flow.load() και εκτελέστε την με το exec()

Total.js 5 · total5@0.0.19 flowflowstreamcomponentsautomation Εκτελέστηκε με το Total.js 5

Ένα 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). Μη φορτώνετε ποτέ σχήμα ή συνιστώσα που μπορεί να γράψει ένας επισκέπτης.

definitions/flow.js
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;
});
controllers/flow.js
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) });
}