2012-11-04 27 views
34

मुझे यकीन है कि मेरी समस्या node.js में asynch प्रोग्रामिंग की समझ की कमी पर आधारित है लेकिन यहां जाती है।नोड.जेएस: एसिंक्रोनस कॉलबैक में चर कैसे पास करें?

उदाहरण के लिए: मेरे पास लिंक की एक सूची है जिसे मैं क्रॉल करना चाहता हूं। जब प्रत्येक एसिंच अनुरोध लौटाता है तो मैं जानना चाहता हूं कि यह किस URL के लिए है। लेकिन, संभवतः दौड़ की स्थितियों के कारण, प्रत्येक अनुरोध सूची में अंतिम मान पर यूआरएल सेट के साथ आता है।

var links = ['http://google.com', 'http://yahoo.com']; 
for (link in links) { 
    var url = links[link]; 
    require('request')(url, function() { 
     console.log(url); 
    }); 
} 

अपेक्षित उत्पादन:

http://google.com 
http://yahoo.com 

वास्तविक उत्पादन:

http://yahoo.com 
http://yahoo.com 

तो मेरे सवाल है या तो:

  1. कैसे करें मैं यूआरएल (मूल्य) के द्वारा पारित कर वापस काम कॉल करें? या
  2. HTTP अनुरोधों को चेन करने का सही तरीका क्या है ताकि वे अनुक्रमिक रूप से चल सकें? या
  3. कुछ और मुझे याद आ रही है?

पीएस: 1 के लिए। मुझे ऐसा समाधान नहीं चाहिए जो कॉलबैक के पैरामीटर की जांच करे लेकिन कॉलबैक का सामान्य तरीका ऊपर से 'चर' के बारे में जान सके।

उत्तर

46

आपका url वैरिएबल for लूप पर नहीं है क्योंकि जावास्क्रिप्ट केवल वैश्विक और फ़ंक्शन स्कोपिंग का समर्थन करता है। तो तुम एक तत्काल फ़ंक्शन का उपयोग करके लूप के प्रत्येक चरण में url मूल्य पर कब्जा करने के अपने request कॉल के लिए एक समारोह गुंजाइश बनाने की जरूरत: Btw

var links = ['http://google.com', 'http://yahoo.com']; 
for (link in links) { 
    (function(url) { 
     require('request')(url, function() { 
      console.log(url); 
     }); 
    })(links[link]); 
} 

, पाश के बीच में एक require embedding अच्छा नहीं है अभ्यास। यह शायद फिर से लिखा जाना चाहिए, क्योंकि:

var request = require('request'); 
var links = ['http://google.com', 'http://yahoo.com']; 
for (link in links) { 
    (function(url) { 
     request(url, function() { 
      console.log(url); 
     }); 
    })(links[link]); 
} 
+3

यह दायरे के बारे में नहीं है। यह बंद होने के बारे में है। कई अन्य भाषाओं में ब्लॉक स्कोप नहीं है, फिर भी बंद होने की कमी के कारण इस मुद्दे का सामना नहीं करते हैं। – slebetman

+3

बिंदु यह है कि यदि जावास्क्रिप्ट ने ब्लॉक स्कोप का समर्थन किया है, तो ओपी के कोड के कॉलबैक फ़ंक्शन में 'url' को बंद करने का उपयोग काम करेगा क्योंकि लूप के प्रत्येक पुनरावृत्ति को अपना' url' चर (जैसे सी #) प्राप्त होगा। – JohnnyHK

+1

आवश्यकता सिर्फ ब्रुविटी के लिए है, मेरे कोड में सभी आवश्यक शुरुआत में हैं। – Marc

8

इस मुद्दे की सामान्य चर्चा के लिए https://stackoverflow.com/a/11747331/243639 देखें।

मैं की तरह

var links = ['http://google.com', 'http://yahoo.com']; 

function createCallback(_url) { 
    return function() { 
     console.log(_url); 
    } 
}; 

for (link in links) { 
    var url = links[link]; 
    require('request')(url, createCallback(url)); 
} 
+0

समस्या की व्याख्या करने के लिए स्टैक ओवरव्लो पर देने के लिए बहुत से बेहतर लिंक हैं। उदाहरण के लिए यह एक: http://stackoverflow.com/questions/3572480/please-explain-the-use-of-javascript-closures-in-loops/3572616#3572616 – slebetman

8

चेक इस blog बाहर कुछ सुझाव देना चाहेंगे। एक चर को .bind() विधि का उपयोग करके पारित किया जा सकता है। आपके मामले में यह इस तरह होगा:

var links = ['http://google.com', 'http://yahoo.com']; 
for (link in links) { 
var url = links[link]; 

require('request')(url, function() { 

    console.log(this.urlAsy); 

}.bind({urlAsy:url})); 
} 
+1

मुझे इस विधि को और अधिक पसंद है क्योंकि यह बहुत कम वर्बोज़ है एक समारोह में कुछ लपेटना। –