Node.js मॉड्यूल को समझना: कई को एक ही वस्तु को वापस करने की आवश्यकता होती है?


106

मेरे पास मॉड्यूल कैशिंग पर नोड.जेएस प्रलेखन से संबंधित एक प्रश्न है :

पहली बार लोड किए जाने के बाद मॉड्यूल को कैश किया जाता है। इसका मतलब है (अन्य चीजों के बीच) कि आवश्यकता के लिए हर कॉल ('फू') को उसी वस्तु को वापस मिलेगा , यदि वह उसी फ़ाइल को हल करेगी।

आवश्यकता के लिए कई कॉल ('फू') मॉड्यूल कोड को कई बार निष्पादित करने का कारण नहीं हो सकता है। यह एक महत्वपूर्ण विशेषता है। इसके साथ, "आंशिक रूप से किया गया" वस्तुओं को वापस किया जा सकता है, इस प्रकार सकर्मक निर्भरता को तब भी लोड करने की अनुमति मिलती है जब वे चक्र का कारण बनेंगे।

क्या मतलब है may?

मैं जानना चाहता हूं कि क्या आवश्यकता हमेशा उसी वस्तु को वापस करेगी । तो मामले में मैं एक मॉड्यूल की आवश्यकता होती है एक में app.jsऔर भीतर निर्यात वस्तु को बदलने app.js(एक है कि रिटर्न की आवश्यकता होती है) और उसके बाद एक मॉड्यूल की आवश्यकता बी में app.jsहै जो अपने आप मॉड्यूल की आवश्यकता है एक , तो मैं लूंगा हमेशा उस वस्तु की संशोधित संस्करण, या एक नया मिलता है एक?

// app.js

var a = require('./a');
a.b = 2;
console.log(a.b); //2

var b = require('./b');
console.log(b.b); //2

// a.js

exports.a = 1;

// b.js

module.exports = require('./a');

7
डॉक्स में वह वाक्य बेहतर लिखा जा सकता था। यह मुझे लगता है कि हो सकता है कि अनुमति नहीं है , यानी, कई कॉल करने की आवश्यकता नहीं है ('फू') मॉड्यूल कोड को कई बार निष्पादित करने का कारण नहीं बन सकता है
लुसियो पावा

@LucioPaiva ने इसे ठीक करने के लिए एक PR बनाया: github.com/nodejs/node/pull/23143
mikemaccana

उनका मतलब था [[हो सकता है] कारण नहीं है, जैसा कि [[हो सकता है] का विरोध नहीं किया गया], इस अर्थ में, "नहीं, टिम्मी, आपके पास कोई और चॉकलेट नहीं हो सकती है"। इसलिए इस संदर्भ में, मैं सहमत हूं, यह अस्पष्ट रूप से लिखा गया है।
सिआब्रोस

जवाबों:


76

दोनों हैं app.jsऔर b.jsरहते हैं एक ही परियोजना में (और एक ही निर्देशिका में) तो उन दोनों को प्राप्त होगा एक ही उदाहरण के Aनोड से। प्रलेखन :

... हर कॉल करने के require('foo')लिए वास्तव में एक ही वस्तु मिलेगी, अगर यह उसी फ़ाइल को हल करेगा ।


स्थिति अलग है जब है a.js, b.jsऔर app.jsकर रहे हैं विभिन्न NPM मॉड्यूल । उदाहरण के लिए:

[APP] --> [A], [B]
[B]   --> [A]

उस स्थिति require('a')में app.jsकी a.jsतुलना require('a')में की एक अलग प्रति को हल करेगा b.jsऔर इसलिए की एक अलग उदाहरण लौटाते हैं A। इस व्यवहार का अधिक विस्तार से वर्णन करने वाला एक ब्लॉग पोस्ट है।


1
"और उसी निर्देशिका में"। मुझे वही उदाहरण मिला जब [B] जहां [App] रहता था, उसके सबफ़ोल्डर में था।
बिल टैरबेल

1
@BillTarbell जब मैं अलग-अलग फ़ोल्डरों से एक ही उदाहरण प्राप्त करना चाहता था तो मुझे दो अलग-अलग मिल गए।
MustSeeMelons

1
क्या यह अंतिम चेतावनी अभी भी सही है कि npm एक फ्लैट डायरेक्टरी स्ट्रक्चर में A, B और APP स्थापित करेगा? यदि नहीं, तो एक मॉड्यूल को कई अन्य मॉड्यूल के बीच परिणाम देने के लिए कैसे सेट किया जा सकता है?
माइकल

नोड.जेएस प्रलेखन से: "मॉड्यूल उनके हल किए गए फ़ाइलनाम के आधार पर कैश किए जाते हैं। चूंकि मॉड्यूल कॉलिंग मॉड्यूल (नोड_मॉडल फ़ोल्डर से लोड) के स्थान के आधार पर एक अलग फ़ाइलनाम का समाधान कर सकता है, यह कोई गारंटी नहीं है:" foo " ') हमेशा वही वस्तु लौटाएगा, अगर वह अलग-अलग फाइलों में हल हो जाएगी।' ' तो आप सिंगलटन व्यवहार, केस असंवेदनशील फ़ाइल सिस्टम या प्रतीकात्मक लिंक को लागू करने के लिए आवश्यक कैश का उपयोग नहीं कर सकते हैं और इस तरह एक ही मॉड्यूल को कई बार लोड किया जा सकता है। यदि आपको वैश्विक डेटा की आवश्यकता है, तो आपको "वैश्विक" ऑब्जेक्ट का उपयोग करने की आवश्यकता है।
टैनिन

6

नोड.जेएस कुछ प्रकार के कैशिंग कार्यान्वित किए गए हैं जो कुछ विशाल सर्वर-प्रोजेक्ट्स को निष्पादित करते समय नोड्स को फ़ाइलों को पढ़ने से रोकते हैं।

यह कैश require.cacheऑब्जेक्ट में सूचीबद्ध है । मुझे यह ध्यान रखना होगा कि यह ऑब्जेक्ट रीड / राइट करने योग्य है जो प्रक्रिया को मारे बिना कैश से फ़ाइलों को हटाने की क्षमता देता है।

http://nodejs.org/docs/latest/api/globals.html#require.cache

उह, सवाल का जवाब देना भूल गया। निर्यात की गई वस्तु को संशोधित करना अगले मॉड्यूल-लोडिंग को प्रभावित नहीं करता है। यह बहुत परेशानी का कारण होगा ... हमेशा वस्तु का एक नया उदाहरण वापस करने की आवश्यकता है, कोई संदर्भ नहीं। फ़ाइल को संपादित करने और कैश को हटाने से निर्यात की गई वस्तु बदल जाती है

कुछ परीक्षण करने के बाद, नोड .js मॉड्यूल.exports को कैश करता है। संशोधन require.cache[{module}].exportsएक नई, संशोधित लौटी वस्तु में समाप्त होता है।


1
मेरे द्वारा पोस्ट किया गया कोड वास्तव में काम करता है। b.bमूल्य के साथ परिभाषित किया गया है 2। तो इस उदाहरण में यह एक ही वस्तु है।
ज़ोम्बी

यह एक विशेषता है और मेरी नजर में काफी उपयोगी है। सवाल यह है कि क्या मैं इस पर निर्भर हो सकता हूं। दस्तावेज़ीकरण कहता है mayजो इसे अस्पष्ट बनाता है।
ज़ोम्बी

A.js में किसी फ़ंक्शन को निष्पादित करने से कुछ भी नहीं बदलता है ... यह लौटी हुई वस्तु को कैशिंग करता है। अजीब, मेरे ऐप कैसे काम करते हैं? एक ही रास्ता है, जैसा कि डॉक्स में वर्णित है, आवश्यकता के बाद एक उत्तीर्ण फ़ंक्शन को निष्पादित करना।
मो

1
कभी-कभी वस्तुएं समान होती हैं। उस पर भरोसा न करें, यदि आप की जरूरत है तो एक मॉड्यूल मॉड्यूल के आसपास से गुजरें।
रिकार्डो तोमासी

क्या किसी आवश्यकता पर ब्रांड की नई वस्तु वापस पाने का एक तरीका है (कैश्ड वस्तु नहीं)?
मैट

3

चूंकि प्रश्न पोस्ट किया गया था, इसलिए यह स्पष्ट करने के लिए दस्तावेज़ को अपडेट किया गया है कि "मूल रूप से" का उपयोग क्यों किया गया था। यह अब चीजों को स्पष्ट करके खुद ही सवाल का जवाब देता है (मेरा जोर यह दिखाने के लिए है कि क्या बदला है):

पहली बार लोड किए जाने के बाद मॉड्यूल को कैश किया जाता है। इसका मतलब है (अन्य चीजों के बीच) कि आवश्यकता के लिए हर कॉल ('फू') को उसी वस्तु को वापस मिलेगा, यदि वह उसी फ़ाइल को हल करेगी।

बशर्ते आवश्यकता है। कैश को संशोधित नहीं किया गया है, आवश्यकता के लिए कई कॉल ('फू') मॉड्यूल कोड को कई बार निष्पादित करने का कारण नहीं होगा । यह एक महत्वपूर्ण विशेषता है। इसके साथ, "आंशिक रूप से किया गया" वस्तुओं को वापस किया जा सकता है, इस प्रकार सकर्मक निर्भरता को तब भी लोड करने की अनुमति मिलती है जब वे चक्र का कारण बनेंगे।


2

मैंने जो देखा है, उसके लिए, यदि मॉड्यूल का नाम लोड किए गए फ़ाइल के लिए निर्धारित होता है, तो कैश्ड मॉड्यूल वापस कर दिया जाएगा, अन्यथा नई फ़ाइल को अलग से लोड किया जाएगा।

यही है, कैशिंग वास्तविक फ़ाइल नाम पर आधारित है जो हल हो जाता है। ऐसा इसलिए है क्योंकि सामान्य तौर पर, एक ही पैकेज के विभिन्न संस्करण हो सकते हैं जो फ़ाइल पदानुक्रम के विभिन्न स्तरों पर स्थापित होते हैं और जिन्हें तदनुसार लोड किया जाना चाहिए।

मुझे इस बात पर यकीन नहीं हो रहा है कि कैश के अमान्य होने के मामले हैं जो कि प्रोग्रामर के नियंत्रण या जागरूकता के तहत नहीं हैं, जो कि कई बार एक ही पैकेज फ़ाइल को आकस्मिक रूप से पुनः लोड करना संभव बना सकते हैं।


1

इस कारण से कि आप require(x)हर बार एक नई वस्तु क्यों लौटना चाहते हैं , क्योंकि आप उस वस्तु को सीधे संशोधित करते हैं - जो एक ऐसा मामला है जिसमें मैं भाग गया - बस इसे क्लोन करें, और केवल क्लोन को संशोधित और उपयोग करें, जैसे:

var a = require('./a');
a = JSON.parse(JSON.stringify(a));

0

drex का प्रयास करें : https://github.com/yuryb/drex

drex अपडेट के लिए एक मॉड्यूल देख रहा है और अपडेट के बाद साफ़-साफ़ मॉड्यूल की आवश्यकता है। नए कोड की आवश्यकता है () d के रूप में यदि नया कोड एक पूरी तरह से अलग मॉड्यूल है, तो आवश्यकता है। Cache कोई समस्या नहीं है।


2
सवाल एक और था, लेकिन विकास के सामान के लिए drex वास्तव में अच्छा लग रहा है। धन्यवाद!
एलेक्स इवासेवु

0

जब आपको किसी ऑब्जेक्ट की आवश्यकता होती है, तो आपको उसके संदर्भ पते की आवश्यकता होती है, और ऑब्जेक्ट को दो बार आवश्यकता होने पर, आपको वही पता मिलेगा! एक ही ऑब्जेक्ट की प्रतियां होने के लिए, आपको इसे (क्लोन) कॉपी करना चाहिए।

var obj = require('./obj');

a = JSON.parse(JSON.stringify(obj));
b = JSON.parse(JSON.stringify(obj));
c = JSON.parse(JSON.stringify(obj));

क्लोनिंग कई मायनों में किया जाता है, आप देख सकते हैं इस अधिक जानकारी के लिए,।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.