Saya telah bekerja dengan nodejs akhir-akhir ini dan masih memahami sistem modul jadi minta maaf jika ini adalah pertanyaan yang jelas. Saya ingin kode kira-kira seperti berikut ini:
a.js (file utama dijalankan dengan node)
var ClassB = require("./b");
var ClassA = function() {
this.thing = new ClassB();
this.property = 5;
}
var a = new ClassA();
module.exports = a;
b.js
var a = require("./a");
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
util.log(a.property);
}
module.exports = ClassB;
Masalah saya sepertinya saya tidak bisa mengakses instance dari ClassA dari instance ClassB.
Apakah ada cara yang benar / lebih baik untuk menyusun modul untuk mencapai apa yang saya inginkan? Apakah ada cara yang lebih baik untuk berbagi variabel antar modul?
node.js
module
require
cyclic-reference
cyclic-dependency
Dapat diakses
sumber
sumber
Jawaban:
Meskipun node.js memungkinkan
require
dependensi melingkar , seperti yang Anda temukan itu bisa sangat berantakan dan Anda mungkin lebih baik merestrukturisasi kode Anda untuk tidak membutuhkannya. Mungkin membuat kelas ketiga yang menggunakan dua lainnya untuk mencapai apa yang Anda butuhkan.sumber
exports = {}
di bagian atas kode Anda dan kemudianexports = yourData
di akhir kode Anda. Dengan latihan ini Anda akan menghindari hampir semua kesalahan dari dependensi melingkar.Cobalah untuk mengaktifkan properti
module.exports
, alih-alih menggantinya sepenuhnya. Misalnya,module.exports.instance = new ClassA()
dalama.js
,module.exports.ClassB = ClassB
dalamb.js
. Ketika Anda membuat dependensi modul melingkar, modul yang membutuhkan akan mendapatkan referensi ke yang tidak lengkapmodule.exports
dari modul yang diperlukan, yang Anda dapat menambahkan properti lain yang terakhir, tetapi ketika Anda mengatur keseluruhanmodule.exports
, Anda benar-benar membuat objek baru yang modul yang membutuhkan tidak memiliki cara mengakses.sumber
module.exports
tanpa sepenuhnya menggantinya, untuk memungkinkan kelas lain 'membangun' contoh kelas?[EDIT] ini bukan tahun 2015 dan sebagian besar perpustakaan (yaitu express) telah membuat pembaruan dengan pola yang lebih baik sehingga dependensi melingkar tidak lagi diperlukan. Saya sarankan tidak menggunakannya .
Saya tahu saya sedang menggali jawaban lama di sini ... Masalahnya di sini adalah module.exports didefinisikan setelah Anda memerlukan ClassB. (yang ditunjukkan oleh tautan JohnnyHK) Ketergantungan melingkar bekerja dengan baik di Node, mereka hanya didefinisikan secara sinkron. Ketika digunakan dengan benar, mereka sebenarnya memecahkan banyak masalah simpul umum (seperti mengakses express.js
app
dari file lain)Pastikan ekspor yang diperlukan sudah ditentukan sebelumnya Anda memerlukan file dengan ketergantungan melingkar.
Ini akan merusak:
Ini akan berhasil:
Saya menggunakan pola ini setiap saat untuk mengakses express.js
app
di file lain:sumber
app = express()
Kadang-kadang sangat buatan untuk memperkenalkan kelas ketiga (seperti yang disarankan JohnnyHK), jadi selain Ianzz: Jika Anda ingin mengganti module.exports, misalnya jika Anda membuat kelas (seperti file b.js di contoh di atas), ini dimungkinkan juga, hanya pastikan bahwa dalam file yang memulai lingkaran memerlukan, pernyataan 'module.exports = ...' terjadi sebelum pernyataan memerlukan.
a.js (file utama dijalankan dengan node)
b.js
sumber
Solusinya adalah 'meneruskan menyatakan' objek ekspor Anda sebelum memerlukan pengontrol lain. Jadi jika Anda menyusun semua modul Anda seperti ini dan Anda tidak akan mengalami masalah seperti itu:
sumber
exports.foo = function() {...}
saja. Pasti berhasil. Terima kasih!module.exports
sudah menjadi Obyek biasa secara default, jadi baris "deklarasi maju" Anda berlebihan.Solusi yang membutuhkan perubahan minimal adalah memperluas
module.exports
alih-alih menimpanya.a.js - titik masuk aplikasi dan modul yang menggunakan metode lakukan dari b.js *
b.js - modul yang menggunakan metode do dari a.js
Ini akan bekerja dan menghasilkan:
Sementara kode ini tidak akan berfungsi:
a.js
b.js
Keluaran:
sumber
underscore
, maka ES6Object.assign()
dapat melakukan pekerjaan yang sama dengan yang_.extend()
dilakukan dalam jawaban ini.Bagaimana dengan malas yang hanya membutuhkan saat Anda perlu? Jadi b.js Anda terlihat sebagai berikut
Tentu saja merupakan praktik yang baik untuk meletakkan semua pernyataan yang diperlukan di atas file. Tetapi ada beberapa kesempatan, di mana saya memaafkan diri sendiri karena memilih sesuatu dari modul yang tidak berhubungan. Sebut saja hack, tetapi kadang-kadang ini lebih baik daripada memperkenalkan dependensi lebih lanjut, atau menambahkan modul tambahan atau menambahkan struktur baru (EventEmitter, dll)
sumber
Metode lain yang saya lihat orang lakukan adalah mengekspor di baris pertama dan menyimpannya sebagai variabel lokal seperti ini:
Saya cenderung menggunakan metode ini, apakah Anda tahu tentang kelemahannya?
sumber
module.exports.func1 =
,module.exports.func2 =
Anda dapat menyelesaikan ini dengan mudah: cukup ekspor data Anda sebelum Anda membutuhkan hal lain dalam modul tempat Anda menggunakan module.exports:
classA.js
classB.js
sumber
Mirip dengan jawaban lanzz dan setect, saya telah menggunakan pola berikut:
Para
Object.assign()
salinan anggota keexports
objek yang telah diberikan kepada modul lain.The
=
tugas secara logis berlebihan, karena itu hanya menetapkanmodule.exports
untuk dirinya sendiri, tapi saya menggunakannya karena membantu IDE saya (WebStorm) untuk mengakui bahwafirstMember
adalah properti dari modul ini, sehingga "Go To -> Deklarasi" (Cmd-B) dan perkakas lain akan bekerja dari file lain.Pola ini tidak terlalu cantik, jadi saya hanya menggunakannya ketika masalah ketergantungan siklik perlu diselesaikan.
sumber
Ini adalah solusi cepat yang menurut saya cukup bermanfaat.
Di file 'a.js'
Pada file 'b.js' tulis yang berikut ini
Dengan cara ini pada iterasi berikutnya dari kelas-kelas loop peristiwa akan didefinisikan dengan benar dan pernyataan-pernyataan yang membutuhkan akan bekerja seperti yang diharapkan.
sumber
Sebenarnya saya akhirnya membutuhkan ketergantungan dengan
tidak cantik, tapi berhasil. Ini lebih dimengerti dan jujur daripada mengubah b.js (misalnya hanya menambah modules.export), yang sebaliknya sempurna seperti apa adanya.
sumber
Salah satu cara untuk menghindarinya adalah dengan tidak memerlukan satu file di lain hanya meneruskannya sebagai argumen ke fungsi apa pun yang Anda butuhkan di file lain. Dengan cara ini ketergantungan sirkular tidak akan pernah muncul.
sumber