2012-07-22 15 views
6

मैं फ़ैंटॉमजेएस से server.listen(...) का उपयोग कर रहा हूं। मुझे एहसास है कि यह काफी हद तक प्रयोगात्मक है और इसका उत्पादन में उपयोग नहीं किया जाना चाहिए। मैं इसे एक साधारण स्क्रीनशॉट-सर्वर के लिए उपयोग कर रहा हूं जो यूआरएल के लिए स्क्रीनशॉट उत्पन्न करता है; यह एक खिलौना प्रोजेक्ट है जिसे मैं फैंटॉमजेएस के साथ खेलने के लिए उपयोग कर रहा हूं। मैंने विशेष रूप से लंबे समय से चलने वाले अनुरोधों के साथ एक समस्या देखी है, जहां response ऑब्जेक्ट अनुपलब्ध है। यहाँ मेरी कोड से प्रासंगिक के टुकड़े कर रहे हैं:फ़ैंटॉमजेएस: यह सुनिश्चित करना कि प्रतिक्रिया ऑब्जेक्ट सर्वर में जिंदा रहता है .listen (...)

var service = server.listen(8080, function (request, response) { 

    response.statusCode = 200; 

    if (loglevel === level.VERBOSE) { 
     log(request); 
    } else { 
     console.log("Incoming request with querystring:", request.url); 
    } 

    var params = parseQueryString(request.url); 
    if (params[screenshotOptions.ACTION] === action.SCREENSHOT) { 
     getScreenshot(params, function (screenshot) { 

      response.headers["success"] = screenshot.success; //<-- here is where I get the error that response.headers is unavailable. Execution pretty much stops at that point for that particular request. 
      response.headers["message"] = screenshot.message; 

      if (screenshot.success) { 
       response.write(screenshot.base64); 
      } else { 
       response.write("<html><body>There were errors!<br /><br />"); 
       response.write(screenshot.message.replace(/\n/g, "<br />")); 
       response.write("</body></html>"); 
      } 

      response.close(); 
     }); 
    } else { 
     response.write("<html><body><h1>Welcome to the screenshot server!</h1></body></html>") 
     response.close(); 
    } 
}); 

getScreenshot एक अतुल्यकालिक विधि एक वेबपेज को खोलने के लिए WebPage.open(...) समारोह का उपयोग करता है है; यह कार्य भी असीमित है। तो ऐसा प्रतीत होता है कि जब getScreenshot को तर्क के रूप में पारित किया गया कॉलबैक अंततः कहा जाता है, तो ऐसा लगता है कि response ऑब्जेक्ट पहले से ही हटा दिया गया है। मैं मूल रूप से PhantomJS से निम्न त्रुटि के साथ अंत:

Error: cannot access member `headers' of deleted QObject 

मेरा मानना ​​है कि इस वजह से अनुरोध समयबाह्य और इतने कनेक्शन बंद कर दिया है। दस्तावेज response.write("") पर कॉल करने का उल्लेख करता है ताकि यह सुनिश्चित किया जा सके कि कनेक्शन खुला रहता है। मैंने server.listen(...) की शुरुआत में response.write("") पर कॉल करने का प्रयास किया और मैंने एक सुंदर हैकी समाधान भी कोशिश की जहां मैंने setInterval(...) का उपयोग किया, ताकि प्रत्येक 500 मिलीसेकंड response.write("") निष्पादित किया जा सके (मैंने इसे 50 तक कम कर दिया)। एक बार जब मैंने किया था तो अंतराल को साफ़ करना भी सुनिश्चित किया। हालांकि, मुझे अभी भी यह समस्या मिल रही है।

क्या ऐसा कुछ है जो मुझे तब तक निपटने के लिए जा रहा है जब तक वे वेबसर्वर मॉड्यूल को अधिक मजबूत न बनाते? या इसके चारों ओर एक रास्ता है?

उत्तर

8

मैं इसे समझने में सक्षम था। ऐसा लगता है कि WebPage.open (उदाहरण के लिए http://fark.com और http://cnn.com) के साथ कुछ पेज लोड करते समय एकाधिक onLoadFinished ईवेंट निकाल दिए जाते हैं। इसके परिणामस्वरूप WebPage.open में कॉलबैक में कई बार कॉल किया जा रहा है। तो क्या होता है कि जब नियंत्रण कॉलिंग फ़ंक्शन पर वापस आता है, तो मैंने पहले ही प्रतिक्रिया बंद कर दी है और इसलिए response ऑब्जेक्ट अब मान्य नहीं है। मैंने WebPage.open फ़ंक्शन को कॉल करने से पहले ध्वज बनाने का उपयोग करके इसे ठीक किया है। कॉलबैक के अंदर, मैं यह देखने के लिए ध्वज की स्थिति की जांच करता हूं कि क्या मुझे पहले से ही पिछले onLoadFinished ईवेंट का सामना करना पड़ा है। एक बार जब मैं WebPage.open कॉलबैक के अंदर जो भी करना चाहता हूं, तो मैं यह दिखाने के लिए ध्वज अपडेट करता हूं कि मैंने प्रसंस्करण समाप्त कर लिया है। इस तरह नकली (कम से कम मेरे कोड के संदर्भ में) onLoadFinished घटनाओं को अब सेवा नहीं दी जाती है।

+1

मैंने सर्वर को निष्क्रिय रखने के लिए सर्वर को भी बदल दिया है, जो भी मदद करता है- service = server.listen (पोर्ट, {keepAlive: false}, फ़ंक्शन (अनुरोध, प्रतिक्रिया) {.... – chrismarx

+1

आप बहुत ही अच्छे हैं। धन्यवाद अपनी समस्या को हल करने के तरीके को तोड़ना।बस एक ही मुद्दे में भाग गया। –

+0

क्रिस की टिप्पणी ऊपर - कम से कम फ़ैंटॉमजेएस 1.9.7 के रूप में, ['keepAlive' को 'false' पर डिफ़ॉल्ट]] (https://github.com/ariya/phantomjs/blob/1.9.7/src/webserver.cpp # L116-L118)। – Whymarrh

0

(ध्यान दें कि निम्नलिखित जबकि ओपी संभावना 1.6.1 या उससे अधिक के लिए बात कर रहे थे PhantomJS 1.9.7 को दर्शाता है।)

घटना है कि कई onLoadFinished घटनाओं निकाल दिया जा रहा है में, आप page.open() उपयोग कर सकते हैं onLoadFinished स्वयं को सुनने के बजाए। page.open() का उपयोग करके अपने हैंडलर को एक निजी हैंडलर में लपेटें ताकि यह सुनिश्चित किया जा सके कि आपका कॉलबैक केवल एक बार बुलाया जाता है।

the source से:

definePageSignalHandler(page, handlers, "_onPageOpenFinished", "loadFinished"); 
page.open = function (url, arg1, arg2, arg3, arg4) { 
    var thisPage = this; 
    if (arguments.length === 1) { 
     this.openUrl(url, 'get', this.settings); 
     return; 
    } 
    else if (arguments.length === 2 && typeof arg1 === 'function') { 
     this._onPageOpenFinished = function() { 
      thisPage._onPageOpenFinished = null; 
      arg1.apply(thisPage, arguments); 
     } 
     this.openUrl(url, 'get', this.settings); 
     return; 
    } 
// ... Truncated for brevity 

यह कार्यक्षमता वास्तव में अन्य जवाब के रूप में एक ही है, सरकारी एपीआई के भाग के रूप सामने आ रहा है।