2012-02-16 16 views
7

के साथ प्रगति पट्टी मैं प्रगति पट्टी पर काम कर रहा हूं जो AJAX अनुरोधों और सत्र चर का उपयोग करके प्रगति अद्यतन करता है। जब मेरा प्रोग्राम समय लेने वाले ऑपरेशन करता है जैसे कई ईमेल भेजना आदि। यह उचित सत्र चर सेट करता है (जिसमें प्रगति मूल्य होता है)। यह ऑपरेशन फ़ंक्शन पोस्ट() द्वारा नीचे कोड में शुरू किया गया है।PHP और अजाक्स

इस बीच, दूसरा फ़ंक्शन पूछता है() प्रत्येक 500ms लूप में किया जाता है। इसे वास्तविक समय में वर्तमान प्रगति वापस करनी चाहिए। और यहां समस्या है: पूछे गए सभी अनुरोध() पोस्ट() फ़ंक्शन द्वारा भेजे गए अनुरोध के लिए प्रतीक्षा कर रहे हैं। मजाकिया हिस्सा यह है कि अगर मैं url/to/प्रगति के बजाय google.com जैसे कुछ यूआरएल सेट करता हूं तो यह ठीक काम करता है सिवाय इसके कि यह वही नहीं है जो मैं चाहता हूं :)। जिसका मतलब है कि सर्वर सर्वर पर समस्या है।

यह सुनिश्चित नहीं है कि यह महत्वपूर्ण है लेकिन मैं वाईआई फ्रेमवर्क का उपयोग करता हूं।

नीचे दिया गया सभी कोड केवल स्क्रैच (लेकिन काम कर रहा है) और इसका एकमात्र उद्देश्य यह है कि मेरा मतलब क्या है।

अग्रिम धन्यवाद।

मेरी गरीब अंग्रेज़ी :)

देखें भाग के लिए खेद है:

<script type="text/javascript"> 
function ask() { 
    var d = new Date(); 
    var time = d.getTime(); 
    $.ajax({ 

    type: 'get', 
    url: '/url/to/progress' + '?time=' + time, 
    success: function(data) { 
     $("#progress").html(data); 
    } 
    }) 
} 

function post() { 
    var d = new Date(); 
    var time = d.getTime(); 

    $.ajax({ 
     type: 'post', 
     url: '/url/to/post' + '?time=' + time, 
     data: {"some": "data"}, 
     success: function(data) {alert(data)} 
    }); 
} 

$("#test").click(
    function() { 
    post(); 
    var progress = setInterval("ask();", 500); 
    } 
); 
</script> 

नियंत्रक हिस्सा:

public function actionPost($time) { 
    sleep(5); // time consuming operation 
    echo $time . ' : ' . microtime(); 
    exit; 
} 

public function actionProgress($time) { 
    echo $time . ' : ' . microtime(); 
    exit; 
} 
+0

सर्वर से आपकी प्रतिक्रिया क्या है? देव उपकरण> नेटवर्क> xhr अनुरोध –

उत्तर

9

मुझे लगता है कि यहां आपकी समस्या सत्र से संबंधित है।

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

आप post और progress लिपियों के बीच डेटा साझा करने का एक और तरीका के साथ आने की आवश्यकता होगी - अगर post यह निष्पादन भर खुला सत्र डेटा, progress कभी नहीं जब तक के बाद post निष्पादन पूरा होने सत्र डेटा का उपयोग करने में सक्षम हो जाएगा है । हो सकता है कि आप एक अस्थायी फ़ाइल बनाने के लिए सत्र आईडी का उपयोग कर सकें जो post में लेखन पहुंच है, जिसमें आपने प्रगति सूचक डेटा रखा है। progress फ़ाइल की जांच कर सकते हैं और उस डेटा को वापस कर सकते हैं। आईपीसी (इंटर-प्रोसेस संचार) के लिए कई विकल्प हैं - यह विशेष रूप से सुंदर नहीं है लेकिन इसमें अधिकतम पोर्टेबिलिटी का लाभ होता है।

एक साइड नोट के रूप में - कृपया setInterval() पर तारों को पास न करें, कार्य पास करें। तो अपने लाइन वास्तव में पढ़ना चाहिए:

var progress = setInterval(ask, 500); 

लेकिन - यह ask() ajax समारोह के success/error संचालकों में setTimeout() उपयोग करने के लिए बेहतर होगा। ऐसा इसलिए है क्योंकि setInterval() का उपयोग करके, पिछले एक की स्थिति के बावजूद एक नया अनुरोध शुरू किया जाएगा। अगली अनुरोध शुरू करने से पहले पिछले अनुरोध समाप्त होने तक प्रतीक्षा करना अधिक कुशल होगा। तो मैं इस तरह कुछ और करूँगा:

<script type="text/javascript"> 

    // We'll set this to true when the initail POST request is complete, so we 
    // can easily know when to stop polling the server for progress updates 
    var postComplete = false; 

    var ask = function() { 

    var time = new Date().getTime(); 

    $.ajax({ 

     type: 'get', 
     url: '/url/to/progress' + '?time=' + time, 

     success: function(data) { 
     $("#progress").html(data); 
     if (!postComplete) 
      setTimeout(ask, 500); 
     } 
     }, 
     error: function() { 
     // We need an error handler as well, to ensure another attempt gets scheduled 
     if (!postComplete) 
      setTimeout(ask, 500); 
     } 
     } 

    }); 

    } 

    $("#test").click(function() { 

    // Since you only ever call post() once, you don't need a seperate function. 
    // You can just put all the post() code here. 

    var time = new Date().getTime(); 

    $.ajax({ 

     type: 'post', 
     url: '/url/to/post' + '?time=' + time, 
     data: { 
     "some": "data" 
     }, 

     success: function(data) { 
     postComplete = true; 
     alert(data); 
     } 
     error: function() { 
     postComplete = true; 
     } 

    }); 

    if (!postComplete) 
     setTimeout(ask, 500); 
    } 

    }); 

</script> 

... हालांकि यह अभी भी सत्र की समस्या को ठीक नहीं करता है।

+0

पर जांचें आप कठोर थे। मुझे function session_write_close() मिला और ऐसा लगता है कि यह काम कर रहा है! मुझे बस इतना करना था कि कार्रवाई की शुरुआत में सत्र बंद करना और केवल मेरे सत्र चर को अपडेट करने के लिए इसे फिर से खोलना था। आपकी सलाह के लिए बहुत बहुत धन्यवाद और धन्यवाद। उद्घाटन और एक ही स्क्रिप्ट में सत्र डेटा को कई बार बंद करने से सावधान रहें – pawelo

+0

- मैंने देखा है लोग शिकायत करते हैं कि यह मज़बूती से काम नहीं करता है, तो सुनिश्चित करें कि आप अच्छी तरह से कुछ भी आप के साथ आते हैं जांच करें। – DaveRandom

+0

हम्म, शायद बेहतर समाधान डीबी या फ़ाइल में प्रगति चर को स्टोर करना है। मुझे इसे देखना चाहिए, धन्यवाद! – pawelo

6

@ डेवआरैंडम ऊपर से सही ढंग से इंगित करता है कि आप सत्र स्टोरेज लॉक का शिकार हैं।

कामकाज काफी सरल है। आप स्क्रिप्ट बनाना चाहते हैं जो post() को सत्र डेटा पर लॉक जारी करता है ताकि ask() को संभालने वाली स्क्रिप्ट इस सत्र डेटा तक पहुंच सके। आप session_write_close के साथ ऐसा कर सकते हैं।

बारीक अक्षरों यहाँ तो आप उसके अनुसार post के लिए स्क्रिप्ट की संरचना की जरूरत है कि session_write_close बुला के बाद आप सत्र चर के लिए पहुँच नहीं होगा, है:

  1. सभी डेटा आप $_SESSION से की जरूरत है और एक बचत होगी पढ़ें इसकी प्रति
  2. सत्र लॉक को रिलीज़ करने के लिए session_write_close पर कॉल करें।
  3. अपना लंबा ऑपरेशन जारी रखें। यदि आपको सत्र डेटा की आवश्यकता है, तो इसे अपनी प्रतिलिपि से बाहर निकालें और $_SESSION सीधे नहीं।

वैकल्पिक रूप से, आप स्क्रिप्ट के जीवनकाल के दौरान सत्र पर कई बार ताला टॉगल कर सकते हैं:

session_start(); 
$_SESSION['name'] = 'Jon'; 

// Quick operation that requires session data 
echo 'Hello '.$_SESSION['name']; 

// Release session lock 
session_write_close(); 

// Long operation that does not require session data. 
sleep(10); 

// Need access to session again 
session_start(); 
echo 'Hello again '.$_SESSION['name']; 

यह व्यवस्था यह बनाता है ताकि स्क्रिप्ट यह सो, अन्य लिपियों के बिना सत्र डेटा एक्सेस कर सकें समस्या का।

+0

मैं लगभग ने कहा, "बस का उपयोग' session_write_close() '' post' लिपि में "सवाल जब तक मैं फिर से पढ़ और महसूस किया कि वह क्या करने के लिए कोशिश कर रहा है सत्र डेटा के माध्यम से लंबा के कार्यों की प्रगति का हिस्सा है। जो स्पष्ट रूप से, आप नहीं कर सकते हैं। आप की कोशिश कर सकते हैं और 'session_write_close()' और बाद में 'session_start()' आप प्रगति की जानकारी अद्यतन करने की आवश्यकता है जब - अपने आप को मैं इस की कोशिश कभी नहीं की है, लेकिन मैं यहाँ एक सवाल देख रहा था जहां किसी को खोजने के लिए इस काम नहीं किया याद, इसलिए करते हैं अगर यह कहीं भी काम करता है तो शायद यह हर जगह काम नहीं करेगा। इसलिए 'आपको डेटा साझा करने के किसी अन्य तरीके से आने की आवश्यकता होगी' – DaveRandom