ForgeTotal.js 5
el

Total.js 5

Φορτώστε μια ενότητα JavaScript από URL με το IMPORT()

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

Το IMPORT(url, [callback]) κατεβάζει ένα αρχείο JavaScript, το αποθηκεύει στον φάκελο tmp της εφαρμογής και επιστρέφει ό,τι εξάγει το αρχείο (module.exports), όπως θα έκανε το require(). Με callback είναι callback(err, module, response)· χωρίς αυτό, το IMPORT() επιστρέφει ένα promise για την ενότητα. Η διεύθυνση θυμάται: η νέα κλήση του IMPORT() με την ίδια διεύθυνση δεν κατεβάζει ξανά το αρχείο, φορτώνει με require αυτό που είναι στο tmp (και το αρχείο μένει εκεί ανάμεσα στις επανεκκινήσεις, αλλά η μνήμη του «έχει ήδη κατέβει» όχι: μετά από επανεκκίνηση κατεβαίνει ξανά).

Αυτό εκτελεί κώδικα που έρχεται από το δίκτυο με όλα τα δικαιώματα της εφαρμογής σας. Κάντε εισαγωγή μόνο από διεύθυνση που ελέγχετε και φτάνετε με https, ποτέ από μια που σας έστειλε ένας χρήστης ή που μπορεί να αλλάξει οποιοσδήποτε άλλος. Το αρχείο είναι ενότητα CommonJS. Η κατάσταση της απάντησης δεν ελέγχεται: μια διεύθυνση που απαντά 404 (ή οποιαδήποτε σελίδα σφάλματος) αποθηκεύεται σαν να ήταν η ενότητα και το require() πετά τότε ένα SyntaxError μέσα στη λήψη, οπότε στο total5 0.0.19 το callback δεν καλείται ποτέ και το promise δεν ολοκληρώνεται ποτέ. Δώστε πάντα στο IMPORT() ένα δικό σας χρονικό όριο, όπως κάνει η τελευταία διαδρομή, και ελέγξτε τη διεύθυνση πριν βασιστείτε σε αυτήν.

Εδώ το αρχείο προέρχεται από μια διαδρομή της ίδιας εφαρμογής, ώστε το παράδειγμα να μη χρειάζεται δίκτυο. Η διαδρομή μετρά τις λήψεις.

controllers/import.js
exports.install = function() {
	ROUTE('GET /lib/tax/', lib);
	ROUTE('POST /use/', use);
	ROUTE('POST /use-twice/', use_twice);
	ROUTE('POST /missing/', missing);
	ROUTE('GET /downloads/', downloads);
};

let count = 0;

function lib($) {
	count++;
	$.plain('module.exports = { vat: function(price) { return Math.round(price * 121) / 100; } };');
}

function downloads($) {
	$.json({ downloads: count });
}

function base() {
	return 'http://127.0.0.1:' + CONF.$port;
}

async function use($) {
	const tax = await IMPORT(base() + '/lib/tax/');
	$.json({ price: tax.vat(100) });
}

function use_twice($) {
	IMPORT(base() + '/lib/tax/', function(err, tax) {
		$.json({ err: err ? err.toString() : null, price: tax ? tax.vat(200) : null });
	});
}

async function missing($) {
	// the address does not exist: the answer is the 404 page of the application
	const winner = await Promise.race([
		IMPORT(base() + '/lib/missing/').then(() => 'answered', () => 'answered'),
		new Promise(resolve => setTimeout(() => resolve('no answer'), 1500))
	]);
	$.json({ result: winner });
}