Muat dan jalankan file js eksternal di node.js dengan akses ke variabel lokal?

130

Apakah mudah / mungkin untuk melakukan include('./path/to/file')jenis perintah sederhana di node.js?

Yang ingin saya lakukan adalah memiliki akses ke variabel lokal dan menjalankan skrip. Bagaimana orang biasanya mengatur proyek node.js yang lebih besar dari dunia halo sederhana? (Situs web dinamis yang berfungsi penuh)

Misalnya saya ingin memiliki direktori seperti:

/models

/views

... dll

Travis
sumber
Dimungkinkan juga untuk memasukkan skrip dari URL eksternal (bukan file lokal). Lihat di sini: pastebin.com/WkvHjGsG
Anderson Green
Skrip di atas hanya berfungsi dengan benar jika Anda membuat folder yang disebut downloadedModulesdi direktori yang sama dengan skrip.
Anderson Green

Jawaban:

134

Lakukan saja require('./yourfile.js');

Nyatakan semua variabel yang Anda inginkan di luar akses sebagai variabel global. Jadi, bukannya

var a = "hello" boleh jadi

GLOBAL.a="hello" atau hanya

a = "hello"

Ini jelas buruk. Anda tidak ingin mencemari ruang lingkup global. Sebaliknya metode yang disarankan adalah untuk exportfungsi / variabel Anda.

Jika Anda ingin pola MVC lihatlah Geddy.

Shripad Krishna
sumber
3
Sebagai catatan. Saya suka Express. Anda harus memeriksanya juga, asalkan Anda tidak terlalu khusus tentang MVC.
Shripad Krishna
43
Ketika Anda mengatakan "ini jelas buruk", apa yang dimaksud dengan "ini"?
Anderson Green
1
@AndersonGreen - Maksudnya menempatkan variabel dalam lingkup global.
Tim
77
@AndersonGreen: Tolong beritahu saya itu adalah lelucon yang sangat pintar tentang pelingkupan ;-)
Dusty J
6
Ini membantu saya untuk mempelajari yang requireterlihat di modul npm Anda jika Anda tidak mengawali jalur Anda dengan sesuatu seperti./
Dylan Valade
93

Anda perlu memahami CommonJS, yang merupakan pola untuk mendefinisikan modul. Anda tidak boleh menyalahgunakan ruang lingkup GLOBAL yang selalu merupakan hal yang buruk untuk dilakukan, alih-alih Anda dapat menggunakan token 'ekspor', seperti ini:

// circle.js

var PI = 3.14; // PI will not be accessible from outside this module

exports.area = function (r) {
  return PI * r * r;
};

exports.circumference = function (r) {
  return 2 * PI * r;
};

Dan kode klien yang akan menggunakan modul kami:

// client.js

var circle = require('./circle');
console.log( 'The area of a circle of radius 4 is '
           + circle.area(4));

Kode ini diekstraksi dari API dokumentasi node.js:

http://nodejs.org/docs/v0.3.2/api/modules.html

Juga, jika Anda ingin menggunakan sesuatu seperti Rails atau Sinatra, saya sarankan Express (saya tidak bisa memposting URL, malu Stack Overflow!)

Ivan Torres
sumber
64

Jika Anda menulis kode untuk Node, menggunakan modul Node seperti yang dijelaskan oleh Ivan adalah cara yang pasti.

Namun, jika Anda perlu memuat JavaScript yang sudah ditulis dan tidak mengetahui node, vmmodul adalah cara untuk pergi (dan pasti lebih disukai eval).

Sebagai contoh, ini adalah execfilemodul saya , yang mengevaluasi skrip di pathdalam contextkonteks global atau global:

var vm = require("vm");
var fs = require("fs");
module.exports = function(path, context) {
  var data = fs.readFileSync(path);
  vm.runInNewContext(data, context, path);
}

Perhatikan juga: modul yang dimuat dengan require(…)tidak memiliki akses ke konteks global.

David Wolever
sumber
1
Terima kasih atas tip ini. Kasing penggunaan sebenarnya adalah ketika Anda perlu memuat modul adhoc. Katakanlah seperti pola pendaftaran di mana Anda akan memiliki 1000 modul yang mendaftar di layanan pusat. Ini jauh lebih bersih dan desain yang lebih baik untuk memindai modul dan memuatnya satu per satu daripada melakukan 1000 memerlukan pernyataan dalam layanan Anda ...
Assaf Moldavsky
Node mendukung kebutuhan dinamis, jadi tidak ada alasan untuk menggunakan pola ini saat memuat modul sadar-Node secara dinamis. Bahkan, itu berbahaya untuk digunakan di sana, karena melewati Node require.cache, jadi satu file dapat dimuat beberapa kali.
David Wolever
Ok, jadi untuk menyelesaikan kasus yang saya sajikan di mana Anda memiliki 1000 modul di mana masing-masing mendaftar ke layanan registri, bagaimana Anda menggunakan apa yang Anda usulkan tanpa memiliki 1000 pernyataan di layanan registri?
Assaf Moldavsky
1
Sama requireseperti biasa: function loadService(name) { return require('./services/' + name); }kemudian daftarkan layanan namun masuk akal untuk aplikasi.
David Wolever
Benar, tetapi itu menyiratkan Anda harus tahu semua 1000 modul dalam layanan registri. Yang tidak lebih baik daripada memiliki 1000 memerlukan pernyataan. Seluruh idenya adalah bahwa layanan registri tidak mengetahui semua modul dan pada kenyataannya tidak peduli tentang mereka. Modul mendaftar ad hoc ke dalam layanan registri. Apakah itu masuk akal?
Assaf Moldavsky
7

Jika Anda berencana untuk memuat fungsi atau objek file javascript eksternal, muat pada konteks ini menggunakan kode berikut - perhatikan metode runInThisContext:

var vm = require("vm");
var fs = require("fs");

var data = fs.readFileSync('./externalfile.js');
const script = new vm.Script(data);
script.runInThisContext();

// here you can use externalfile's functions or objects as if they were instantiated here. They have been added to this context. 
Rox
sumber
2
Setelah banyak mencari dan menipu, teknik ini berhasil untuk saya. File saya ditulis untuk digunakan browser secara langsung dan mendeklarasikan variabel mis: const aVar = {thing: 'a'}
lucsan
3

Memperluas jawaban @Shripad dan @Ivan , saya akan merekomendasikan agar Anda menggunakan fungsionalitas module.export standar Node.js.

Dalam file Anda untuk konstanta ( misalnya constants.js ), Anda akan menulis konstanta seperti ini:

const CONST1 = 1;
module.exports.CONST1 = CONST1;

const CONST2 = 2;
module.exports.CONST2 = CONST2;

Kemudian di file di mana Anda ingin menggunakan konstanta itu, tulis kode berikut:

const {CONST1 , CONST2} = require('./constants.js');

Jika Anda belum pernah melihat const { ... }sintaksis sebelumnya: itu adalah penugasan yang merusak .

Jonathan Benn
sumber
0

Maaf untuk kebangkitan. Anda bisa menggunakan modul child_process untuk mengeksekusi file js eksternal di node.js

var child_process = require('child_process');

//EXECUTE yourExternalJsFile.js
child_process.exec('node yourExternalJsFile.js', (error, stdout, stderr) => {
    console.log(`${stdout}`);
    console.log(`${stderr}`);
    if (error !== null) {
        console.log(`exec error: ${error}`);
    }
});
lupu51nfactum N778
sumber