2014-07-16 3 views
6

के लिए पोस्ट अनुरोध भेजना मैं लूप में पोस्ट अनुरोध भेजना चाहता हूं। यदि मैं पंक्ति में उदाहरण के लिए 2 अनुरोध भेजता हूं तो केवल अंतिम अनुरोध ने वास्तव में कॉलबैक बनाया है।लूप

मैं क्या गलत कर रहा हूँ?

this.assignAUnits = function(){ 
     var currentIncidentId = this.incident.incidentId; 
     for (var i=0; i< this.selectedAvailableUnits.length; i++){ 
      var unit = this.selectedAvailableUnits[i]; 
      var unitId = unit.unitId; 

      var url = '/incident/' + currentIncidentId + '/assignUnit/' + unitId 

      $http.post(url).then(function(response) { 
       DOING SOMETHING 

      }, function(error) { 
       alert(error); 
      });   
     } 
    }; 
+4

क्या आप ब्राउज़र नेटवर्क टैब में जांच सकते हैं, वास्तव में केवल एक ही अनुरोध भेजा गया है ?? – harishr

+0

@ mr-question कृपया उत्तर की समीक्षा करने के लिए अपना समय लें और सही एक – domokun

उत्तर

4

closure का उपयोग करें। मैं आपको एक सरल उदाहरण

// JavaScript on Client-Side 
window.onload = function() { 
    var f = (function() { 
     for (i = 0; i < 3; i++) { 
      (function(i){ 
       var xhr = new XMLHttpRequest(); 
       var url = "closure.php?data=" + i; 
       xhr.open("GET", url, true); 
       xhr.onreadystatechange = function() { 
        if (xhr.readyState == 4 && xhr.status == 200) { 
         console.log(xhr.responseText); // 0, 1, 2 
        } 
       }; 
       xhr.send(); 
      })(i); 
     } 
    })(); 
}; 

// Server-Side (PHP in this case) 
<?php 
    echo $_GET["data"]; 
?> 

दिखाने आपके मामले में ... एक बंद

for (var i=0; i< this.selectedAvailableUnits.length; i++) { 

    (function(i) { // <--- the catch 

     var unit = this.selectedAvailableUnits[i]; 
     var unitId = unit.unitId; 
     var url = '/incident/' + currentIncidentId + '/assignUnit/' + unitId 
     $http.post(url).then(function(response) { 
      // DOING SOMETHING 
     }, function(error) { 
      alert(error); 
     }); 

    })(i); // <---- (the i variable might be omitted if it's not needed) 

} 

नीचे अनुभाग सीधे प्रश्न से संबंधित नहीं है के साथ अतुल्यकालिक कॉल/समारोह लपेट दें बल्कि इस उत्तर से संबंधित टिप्पणियों के लिए।


उदाहरण jsFiddle टिप्पणी में उल्लेख किया है पर प्रस्तुत की है और नीचे दिखाया गया है गाड़ी है और इस तरह के रूप में यह कुछ भी साबित नहीं होता।

यह सच है कि यह स्निपेट, बंद होने का उपयोग भी नहीं करता है, 'हैलो किट्टी' तीन बार पैदा करता है; वास्तव में, यदि आप console.log() विधि को alert() के साथ प्रतिस्थापित करते हैं, तो आप देखेंगे कि यह 'हैलो किट्टी' छह, नौ या यहां तक ​​कि बारह बार उत्पन्न करता है। तो, क्या चल रहा है;) चेतावनी खिड़की को तीन पुनरावृत्तियों के लूप के भीतर छह, नौ या बारह बार पॉप अप करना संभव है ?!

// your example (a)         // my comments 
// 
var f = (function() { 
    for (i = 0; i < 3; i++) { 
     //(function(){        // this way you can't have multiple scopes 
      var xhr = new XMLHttpRequest(); 
      var url = "closure.php?data=your-data"; // use /echo/html/ for testing on jsfiddle.net 
      xhr.open("GET", url, true);    // use POST for testing on jsfiddle.net 
      xhr.onreadystatechange = function() { // this way you might catch all readyStage property values 
       callback();       // this way the callback function will be called several times 
      }; 
      xhr.send(); 
     //})(); 
    } 
})(); 

var callback = function() { 
    console.log("Hello Kitty"); // or use alert("Hello Kitty"); 
}; 

आउटपुट:

GET http://fiddle.jshell.net/_display/closure.php?data=your-data 404 (NOT FOUND) 
(9) Hello Kitty 

आप देख सकते हैं के रूप में, हम एक त्रुटि और नौ 'हैलो किटी' एक पंक्ति में आउटपुट :) इससे पहले कि मैं समारोह को बदलने के ऊपर देखते दो महत्वपूर्ण जाने मिल गया है बात

पहले

onreadystatechange घटना भंडार readyState संपत्ति परिवर्तन में status संपत्ति में XMLHttpRequest ऑब्जेक्ट की स्थिति होती है, प्रत्येक बार स्वचालित रूप से एक फ़ंक्शन या संदर्भ कहा जाता है।

readyState संपत्ति संभावित मान

  • 0:
  • आरंभ नहीं अनुरोध
  • 1: सर्वर कनेक्शन स्थापित
  • 2: अनुरोध प्राप्त हुआ
  • 3: प्रसंस्करण अनुरोध
  • 4: समाप्त अनुरोध और प्रतिक्रिया तैयार है

status संपत्ति संभावित मान

  • 200: ठीक है
  • 404: पृष्ठ नहीं मिला

दूसरा

जैसा कि मैंने टिप्पणी में कहा, jsfiddle.net नहीं करने के लिए विश्वसनीय है कुछ बदलावों के बिना एसिंक्रोनस स्निपेट का परीक्षण करना। दूसरे शब्दों में GET विधि POST को बदला जाना चाहिए और url संपत्ति इस लिंक /echo/html/ लिए परिवर्तित किया जाना चाहिए (के लिए अधिक विकल्प jsFiddle documentation पर एक नज़र डालें) अब

, ऊपर से एक उदाहरण बदल (और टिप्पणियों का पालन करें कोड के भीतर)

// corrected example (b) 
// 
var f = (function() { 
    for (i = 0; i < 3; i++) { 
     //(function(i){            // uncomment this line for the 3rd output        
      var xhr = new XMLHttpRequest(); 
      var url = "/echo/html"; 
      var data = "data"; 
      xhr.open("POST", url, true); 
      xhr.onreadystatechange = function() { 
       //if (xhr.readyState == 4 && xhr.status == 200) { // uncomment this line for the 4th output 
        callback(i, xhr.readyState);      // uncomment this line for the 4th output 
       //} 
      }; 
      xhr.send(data); 
     //})(i);              // uncomment this line for the 3rd output 
    } 
})(); 

var callback = function(i, s) { 
    console.log("i=" + i + " - readyState=" + s + " - Hello Kitty"); 
}; 

1 उत्पादन: // छह आउटपुट

(4) i=3 - readyState=1 - Hello Kitty // four outputs related to readyState value 'server connection established' 
    i=3 - readyState=2 - Hello Kitty // related to readyState value 'request received' 
    i=3 - readyState=4 - Hello Kitty // related to readyState value 'request finished and response is ready' 

2 उत्पादन: // छह आउटपुट

(2) i=3 - readyState=1 - Hello Kitty // two outputs related to readyState value 'server connection established' 
    i=3 - readyState=2 - Hello Kitty // related to readyState value 'request received' 
(3) i=3 - readyState=4 - Hello Kitty // three outputs related to readyState value 'request finished and response is ready' 

उदाहरण में किए गए किसी भी बदलाव के बिना (बी), हमारे पास दो अलग-अलग आउटपुट हैं। जैसा कि आप देख सकते हैं, विभिन्न तैयारस्टेट संपत्ति मूल्यों के लिए अलग-अलग आउटपुट उपज रहे हैं। लेकिन i का मान वही बना रहा।

3 उत्पादन: // उदाहरण में ऊपर showned 3 उत्पादन के लिए लाइनों uncommenting के बाद (ख)

i=0 - readyState=2 - Hello Kitty  // related to readyState value 'request received' 
i=0 - readyState=4 - Hello Kitty  // related to readyState value 'request finished and response is ready' 
i=1 - readyState=2 - Hello Kitty  // ... 
i=1 - readyState=4 - Hello Kitty  // ... 
i=2 - readyState=2 - Hello Kitty 
i=2 - readyState=4 - Hello Kitty 

तो, समारोह जो एक तर्क के रूप i रखती uncommenting के बाद, हम उस मूल्य को देखने के i को सहेजा गया है। लेकिन यह अभी भी गलत है क्योंकि छह आउटपुट हैं और हमें केवल तीन की जरूरत है। हम readyState के सभी मानों या XMLHttpRequest वस्तु की status संपत्ति की जरूरत नहीं है के रूप में, के दो पंक्तियों चौथे उत्पादन के लिए आवश्यक uncomment जाने

4 उत्पादन: // में ऊपर showned 4rd उत्पादन के लिए लाइनों uncommenting के बाद उदाहरण (ख) - अंत में तीन outputs

i=0 - readyState=4 - Hello Kitty 
i=1 - readyState=4 - Hello Kitty 
i=2 - readyState=4 - Hello Kitty 

अंत में, इस स्निपेट का सही संस्करण होना चाहिए और इस हम क्या जरूरत है।

एक अन्य सर्वशक्तिमान, सर्वव्यापी तंत्र (जैसा कि मैंने पहले वर्णित रूप से कहा था) bind() फ़ंक्शन होगा जो मुझे बंद करने से धीमा होने के बाद पसंद नहीं करता है।

+0

हेक्स 4 9 4 डी 4 9 चुनें, आप शायद सही हैं लेकिन मुझे संदेह है कि ओपी विशेष रूप से इस उत्तर से प्रबुद्ध है। श्रीमान प्रश्न, समस्या यह है (हम सोचते हैं) कि '// कुछ ऐसा करना' भाग आपने हमें बताया नहीं है कि वेरिएबल 'i' है। लेकिन यह एक कॉलबैक फ़ंक्शन में है, जो 'लूप' समाप्त होने के बाद तक नहीं चलता है; उसके बाद 'i == this.selectedAvailableUnits.length', इसके मूल मूल्य के बावजूद। इस बंद में 'i' नामक एक नया चर है, जो वास्तव में मूल 'i' से अलग है; यह केवल फ़ंक्शन के भीतर घोषित किया गया है, इसलिए इसका मान लूप के माध्यम से पुनरावृत्ति पर रीसेट नहीं किया गया है। –

+0

@ डेविड नइप 'i' बंद करें और एक पंक्ति में तीन बार गूंजने का प्रयास करें' हैलो किट्टी "बिना बंद किए :) * इस मामले में 'i' महत्वपूर्ण नहीं है। – hex494D49

+0

दूसरे विचारों पर मुझे नहीं लगता कि हम एक-दूसरे को समझते हैं। क्या आप कह रहे हैं कि "हैलो किट्टी" के साथ आखिरी उदाहरण काम नहीं करेगा अगर फ़ंक्शन को कोड के सामान्य ब्लॉक के साथ बदल दिया गया हो? मैं असहमत हूं। आप ऐसा क्यों सोचते हैं? क्या आपके पास इसका प्रदर्शन करने के लिए एक jsfiddle है? –

2

क्षमा करें, मैं AngularJS के साथ काम नहीं है, लेकिन इन दोनों तरीकों कि jQuery या यहाँ तक कि आधार XMLHttpRequest काम अच्छी तरह से उपयोग करके पोस्ट मेरे लिए:

<button onclick="sendWithJQuery()">send</button> 
<ul id="container"></ul> 
<script src="/vendor/bower_components/jquery/dist/jquery.js"></script> 
<script> 
    //use XMLHttpRequest 
    function send(){ 
     for (var i = 1; i <= 10; i++){ 
      var xhr = new XMLHttpRequest(); 
      xhr.open('POST', '/test/' + i); 
      xhr.onreadystatechange = function(){ 
       if (this.readyState != 4){ 
        return; 
       } 
       var li = document.createElement('li'); 
       li.appendChild(document.createTextNode('client time:' + new Date().toISOString() + ', data: ' + this.responseText)); 
       container.appendChild(li); 
      } 
      xhr.send(); 
     } 
    } 

    //use jQuery 
    function sendWithJQuery(){ 
     for (var i = 1; i <= 10; i++){ 
      $.ajax({ 
      url: '/test/' + i, 
      method: "POST", 
      statusCode: { 
       200: function (data, textStatus, jqXHR) { 
        var li = document.createElement('li'); 
        li.appendChild(document.createTextNode('client time:' + new Date().toISOString() + ', data: ' + JSON.stringify(data))); 
        container.appendChild(li); 
       }, 
       500: function (data, textStatus, jqXHR) { 
        alert('Internal server error'); 
       } 
      } 
     }); 
     } 
    } 
</script> 

सर्वर कोड (NodeJS):

router.post('/test/:i', function(req, res) { 
    var i = req.params.i; 
    var t = new Date().toISOString(); 
    setTimeout(function(){ 
     res.send({i: i, t: t}); 
    }, 1000); 
}); 
1

आप for-loop के अंदर एक बदलते चर, url का उपयोग करने का प्रयास कर रहे हैं।

यदि आप लूप के अंदर बंद करने का उपयोग नहीं करते हैं, तो केवल for का अंतिम मान इसे $http.post कॉल पर लाएगा।
लूप के अंदर बंद एक मुश्किल जानवर हो सकता है। यह प्रश्न JavaScript closure inside loops – simple practical example देखें और इसे अधिक सिद्धांत/विवरण के लिए Google करें।

आपका कोड कुछ इस तरह से समायोजित करना होगा:

var doPost = function(url) { 

    $http.post(url).then(
    function(response) { 
     // DOING SOMETHING 
    }, 
    function(error) { 
     alert(error); 
    }); 

} 

this.assignAUnits = function(){ 
     var currentIncidentId = this.incident.incidentId; 
     for (var i=0; i< this.selectedAvailableUnits.length; i++){ 
      var unit = this.selectedAvailableUnits[i]; 
      var unitId = unit.unitId; 

      var url = '/incident/' + currentIncidentId + '/assignUnit/' + unitId 

      doPost(url) 
     } 
    }; 

संपादित करें: अतिरिक्त संदर्भ
मैं एक बहुत ही इसी तरह के मुद्दे लंबे समय तक नहीं पहले था, और आप इसके बारे में यहाँ पढ़ सकते हैं: Angular JS - $q.all() tracking individual upload progress

1

यह स्पष्ट रूप से एक बंद मुद्दा है। और पढ़ें here

यह भी $ http से $ संसाधन का उपयोग करने का सुझाव दिया गया है। (एनजी-संसाधन)।

संसाधन का उपयोग करके लूप के लिए पोस्ट करने के लिए उदाहरण देखें।

 for(var i=0; i<$scope.ListOfRecordsToPost.length; i++){  
      var postSuccessCallback = function(postRec) { 
       console.info('Posted ' + postRec); 
      }($scope.ListOfRecordsToPost[i]); 

      lsProductionService.post({}, postSuccessCallback); 
     }