# Charger un module JavaScript depuis une URL avec IMPORT()

> Téléchargez un fichier JavaScript depuis une adresse, gardez-le dans le dossier tmp, chargez-le avec require et utilisez ce qu'il exporte ; le second appel ne le télécharge pas de nouveau.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: fr
Content-SHA256: 08935c4738098dca95ed6d475dd85f7400abbc424dcf88b6f2d09949b5d567bd
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`IMPORT(url, [callback])` télécharge un fichier JavaScript, l'enregistre dans le dossier `tmp` de l'application et renvoie ce que le fichier exporte (`module.exports`), comme le ferait `require()`. Avec un callback, c'est `callback(err, module, response)` ; sans callback, `IMPORT()` renvoie une promesse du module. L'adresse est mémorisée : appeler de nouveau `IMPORT()` avec la même adresse ne télécharge **pas** le fichier de nouveau, il charge celui de `tmp` (et le fichier reste là entre les redémarrages, mais la mémoire de « déjà téléchargé » non : après un redémarrage il est téléchargé de nouveau).

**Cela exécute du code venant du réseau avec tous les droits de votre application.** N'importez que depuis une adresse que vous contrôlez et que vous atteignez en `https`, jamais une adresse qu'un utilisateur vous a envoyée ou que quelqu'un d'autre peut modifier. Le fichier est un module CommonJS. **L'état de la réponse n'est pas vérifié :** une adresse qui répond `404` (ou une page d'erreur quelconque) est enregistrée comme si c'était le module, puis `require()` lève une `SyntaxError` à l'intérieur du téléchargement, si bien que dans `total5` 0.0.19 le callback n'est **jamais appelé** et la promesse ne se règle jamais. Donnez toujours à `IMPORT()` une limite de temps à vous, comme le fait la dernière route, et vérifiez l'adresse avant de dépendre d'elle.

Ici le fichier vient d'une route de la même application, de sorte que l'exemple n'a pas besoin de réseau. La route compte les téléchargements.

```js 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 });
}
```
