2012-12-07 45 views
5

मैं यह पता लगाने के लिए एक साफ तरीका ढूंढ रहा हूं कि ब्राउज़र में पोस्ट मैसेज ऑब्जेक्ट्स भेजने या प्राप्त करने या केवल स्ट्रिंग का समर्थन करता है या नहीं। मुझे लगता है कि वहां से किसी ने ऐसा कुछ लिखा होगा जो ऐसा करता है लेकिन मुझे कोई समाधान नहीं मिला है।पता लगाएं कि पोस्ट मैसेज ऑब्जेक्ट्स भेज सकता है या नहीं?

मैं वेब वर्कर से डेटा भेजने के लिए पोस्ट मैसेज का उपयोग कर रहा हूं। यह पता लगाने के दौरान कि ब्राउज़र श्रमिकों का समर्थन करता है या नहीं, यह पता लगाने के लिए कि वस्तुओं को पोस्ट के माध्यम से भेजा जा सकता है मैसेज अधिक कठिन साबित हुआ है।

मैं एक साधारण पहचान समारोह लिखना चाहता हूं। इसलिए, यदि ब्राउज़र इसका उपयोग करने के लिए वस्तुओं को भेजने का समर्थन करता है। यदि केवल तारों की अनुमति है तो मैं JSON.stringify() का उपयोग करने के लिए फ़ॉलबैक कर सकता हूं। मैं शायद फ़ंक्शन को डोजो/टेस्ट में असाइन कर दूंगा (हालांकि यह प्रश्न/उत्तर से प्रासंगिक नहीं है)।

इस समस्या को हल करने के लिए अन्य लोगों ने क्या किया है? कोई सलाह बहुत अच्छी होगी, मैं वेबवर्कर्स और पोस्ट मैसेज दोनों के लिए नया हूं। अग्रिम में धन्यवाद।

+0

मुझसे बेवकूफ सवाल - क्या आप एक ही विंडो में 'संदेश पोस्ट कर सकते हैं'? – Ian

+0

@ इयान ... क्या? एक WebWorker (छद्म-) धागे बनाने के लिए एक वर्ग है। आप मूल रूप से एक बाहरी जावास्क्रिप्ट फ़ाइल चला सकते हैं जबकि उस पृष्ठ के भीतर जावास्क्रिप्ट दोषपूर्ण चल रहा है। 'postMessage' आपको उस थ्रेड के साथ संवाद करने की अनुमति देता है। इसमें अलग-अलग खिड़कियों के साथ कुछ भी नहीं है। –

+0

आपकी पहली वाक्य 'पोस्टमेसेज' के साथ संदेश भेजने के बारे में बात करती है। मैं 'पोस्ट मैसेज' देखता हूं और यह अन्य विंडोज़ (जैसे मुझे याद है) को संदेश भेजने के बारे में बात करता है। इस तथ्य को अनदेखा करते हुए कि आप वेब श्रमिकों से बात कर रहे हैं, आप अभी तक एक टेस्ट कॉल क्यों नहीं स्थापित करेंगे? मैं अनुमान लगा रहा हूं कि उनका संचार अलग है, लेकिन यदि आप वर्तमान विंडो में 'ऑनमेज' के लिए श्रोता सेट अप करते हैं और '{}' में पास करते हैं ... तो यह देखने के लिए कि यह एक ऑब्जेक्ट है या नहीं, सिर्फ 'टाइपोफ' जांचें । – Ian

उत्तर

18

मैं अगर postMessage केवल तार का समर्थन करता है या अगर यह अन्य प्रकार का समर्थन करता है पता लगाने के लिए एक और भी आसान रास्ता मिल गया। बस ऑब्जेक्ट पर कस्टम टूस्ट्रिंग-विधि जोड़ें। IE8 और IE9 में postMessage के साथ ऑब्जेक्ट भेजने का प्रयास करते समय उन्हें ऑब्जेक्ट पर toString-method के साथ एक स्ट्रिंग में परिवर्तित कर दिया जाएगा। चूंकि ब्राउज़ करने वाले ऑब्जेक्ट्स का समर्थन करने वाले ब्राउज़र को स्ट्रिंग को कॉल नहीं किया जाता है, इसलिए हम इसका उपयोग हमारे लाभ के लिए कर सकते हैं। यह परीक्षण एसिंक नहीं है, इसलिए आपको तुरंत परिणाम मिल जाएगा। वेब-श्रमिकों के साथ इसका परीक्षण नहीं किया है, लेकिन मुझे लगता है कि आप एक ही तकनीक का उपयोग कर सकते हैं।

var onlyStrings = false; 
try{window.postMessage({toString:function(){onlyStrings=true;}},"*");}catch(e){} 

console.log("Browser only supports postMessage with strings? " + onlyStrings); 

IE8, IE9, IE10 और क्रोम, फायरफॉक्स, सफारी का नवीनतम संस्करण और ओपेरा में परीक्षण किया गया: http://jsbin.com/igowoFaj/1/edit?js,console

अपडेट: कई और अधिक परीक्षण और ब्राउज़रों के साथ एक BrowserScope test किया। निष्कर्ष यह है कि onlyStringsfalse है तो क्लोनबल ऑब्जेक्ट्स, सरणी, संख्या, पिक्सेल डेटा और सरणी बफर भेजने के लिए सुरक्षित है। सिद्धांत रूप में ऑब्जेक्ट भेजने की अनुमति देने वाले सभी ब्राउज़रों को structured clone algorithm का उपयोग करना चाहिए, लेकिन एंड्रॉइड ब्राउज़र और ओपेरा मोबाइल में क्विर्क हैं। ब्राउज़रस्कोप परीक्षण परिणाम पढ़ने के लिए थोड़ा मुश्किल है, क्योंकि send_xxx के लिए 0 केवल समस्याग्रस्त है यदि ब्राउज़र वास्तव में उस प्रकार के लिए समर्थन करता है, तो support_xxx भी जांचें। यदि वे बराबर हैं तो यह ठीक है, लेकिन यदि ब्राउज़र का समर्थन है तो यह एक बग है लेकिन भेज नहीं सकता (जब केवल स्ट्रिंग गलत है)।

2

आप अपनी स्क्रिप्ट को फिर से शुरू करने से पहले एक क्रिया करने का प्रयास कर सकते हैं। आप इस कोशिश कर सकते:

dummy_task.js

self.onmessage = function(event) { 
    self.postMessage(event.data); 
}; 

जावास्क्रिप्ट

workerSupportObject(callback); 

function workerSupportObject(callback) { 
    var callbackIsCalled = false; // to make sure callback isn't run twice 
    var worker = new Worker('dummy_task.js'); // create a worker 

    // create event 
    worker.onmessage = function(event) { 
     // if the value is the same as we sent, it probably works 
     if(!callbackIsCalled) callback.call(null, event.data.value === 'dummy'); 
     callbackIsCalled = true; 
    }; 

    try { 
     // send dummy JSON data 
     worker.postMessage({'value': 'dummy'}); 
    } catch(e) { 
     // oh... an error... clearly that's a no. 
     if(!callbackIsCalled) callback(null, false); 

     callbackIsCalled = true; 
    } 
} 

function callback(objectSupported) { 
    console.log('Worker supports objects: ', objectSupported); 
} 
+0

धन्यवाद, यह बहुत अच्छी तरह से काम करने लग रहा था। यह दुर्भाग्यपूर्ण है कि इसे कॉलबैक के बिना नहीं किया जा सकता क्योंकि यह voids को() फ़ंक्शन में असाइन करने में सक्षम है। यह सुनिश्चित करने के लिए संरचनाओं के बिना() को केवल उपलब्धता के बाद बुलाया जाता है। हालांकि, हम यहां क्या कर रहे हैं की घटना आधारित प्रकृति को देखते हुए कॉलबैक के बिना ऐसा करना असंभव है। आपकी सहायता के लिए धन्यवाद. –

0

postMessage भी iframe रों के बीच काम करता है; यह सोचते हैं कि व्यवहार कार्यकर्ताओं और फ्रेम के बीच में ही है, तो आप इसे पसंद निम्नलिखित या कुछ और प्रयास करना चाहिए:

<html> 
    <body> 
     <iframe id='if'> 

     </iframe> 
     <script> 
     var iframe = document.getElementById('if'); 
     var iframeScript = iframe.contentDocument.createElement("script"); 
     iframeScript.appendChild(
      iframe.contentDocument.createTextNode(
       'window.addEventListener("message", function(e) {console.log(e.data);}); console.log("listener attached");')); 
     iframe.contentDocument.body.appendChild(iframeScript); 
     iframe.contentWindow.postMessage("asdf", "*"); 
     iframe.contentWindow.postMessage({'whatAmI': 'an object, maybe?'}, "*"); 
     </script> 
    </body> 
</html> 

आप कंसोल या console.log परिणाम देखने के लिए सक्षम होने के लिए बदलना पड़ सकता है, लेकिन क्रोम पर, यह मुझे

listener attached about:blank (1):1 
asdf about:blank (1):1 
Object {whatAmI: "an object, maybe?"} about:blank (1):1 

जब मैं इसे स्थानीय फ़ाइल में सहेजता हूं और इसे खोलता हूं।

जेएसफ़िल्ड संस्करण (और संस्करण जो वास्तविक कार्यकर्ता का उपयोग करता है) को पाठक के लिए एक अभ्यास के रूप में छोड़ दिया जाता है। :)

3

मैं वही चीज़ जानना चाहता था। मैंने इस स्क्रिप्ट को यह पता लगाने के लिए बनाया है कि क्या किसी ऑब्जेक्ट को पोस्ट मैसेज में वर्तमान विंडो पर एक साधारण कॉलबैक द्वारा पारित किया जा सकता है। आप आईई 9 रिटर्न झूठी देखेंगे, आईई 10 सच साबित होगा।

http://jsfiddle.net/milesplit/DvqqH/

var supportsPostObject = false; 

(function(){ 
    var callback = function(e) { 
     supportsPostObject = (typeof(e.data)!='string'); 
    }; 
    (window.addEventListener) ? 
     window.addEventListener('message', callback) : 
     window.attachEvent('onmessage', callback); 
    ('postMessage' in window) && window.postMessage({}, '*'); 
})(); 

setTimeout(function(){ 
    alert(supportsPostObject); 
}, 0);