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

> Κατεβάστε ένα αρχείο με JavaScript από μια διεύθυνση, κρατήστε το στον φάκελο tmp, φορτώστε το με require και χρησιμοποιήστε ό,τι εξάγει· η δεύτερη κλήση δεν το κατεβάζει ξανά.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: el
Content-SHA256: 13c899268e6629008dd2ecb089efa88c3920a822131398923cad2f2427c52c10
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

Το `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()` ένα δικό σας χρονικό όριο, όπως κάνει η τελευταία διαδρομή, και ελέγξτε τη διεύθυνση πριν βασιστείτε σε αυτήν.

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

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