Ein JavaScript-Modul mit IMPORT() von einer URL laden
IMPORT(url, [callback]) lädt eine JavaScript-Datei herunter, speichert sie im Ordner tmp der Anwendung und gibt zurück, was die Datei exportiert (module.exports), wie es require() täte. Mit einem Callback ist es callback(err, module, response); ohne ihn gibt IMPORT() ein Promise für das Modul zurück. Die Adresse wird gemerkt: Ein erneuter Aufruf von IMPORT() mit derselben Adresse lädt die Datei nicht erneut herunter, sondern bindet die in tmp ein (und die Datei bleibt zwischen Neustarts dort, das Merken von „schon heruntergeladen“ aber nicht: Nach einem Neustart wird sie erneut heruntergeladen).
Das führt Code aus dem Netz mit allen Rechten deiner Anwendung aus. Importiere nur von einer Adresse, die du kontrollierst und die du per https erreichst, niemals von einer, die dir ein Benutzer geschickt hat oder die jemand anderes ändern kann. Die Datei ist ein CommonJS-Modul. Der Status der Antwort wird nicht geprüft: Eine Adresse, die mit 404 (oder einer beliebigen Fehlerseite) antwortet, wird gespeichert, als wäre sie das Modul, und require() wirft dann innerhalb des Downloads einen SyntaxError, sodass in total5 0.0.19 der Callback nie aufgerufen wird und das Promise nie abgeschlossen wird. Gib IMPORT() immer ein eigenes Zeitlimit, wie es die letzte Route tut, und prüfe die Adresse, bevor du dich darauf verlässt.
Hier stammt die Datei von einer Route derselben Anwendung, sodass das Beispiel kein Netzwerk braucht. Die Route zählt die Downloads.
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 });
}