2011-12-12 10 views
16

अभी तक मैंने केवल पोस्टमेसेज के लिए ट्यूटोरियल देखे हैं जहां एक विंडो एक प्रकार का संदेश भेजती है, और दूसरी विंडो संदेश को केवल एक ही तरीके से व्याख्या करती है।एकाधिक कार्यों या कस्टम कॉलबैक के साथ पोस्टमेसेज

क्या होगा यदि मैं विंडोज़ के बीच कई अलग-अलग प्रकार की बातचीत करना चाहता हूं, तो पोस्टमेसेज हैंडल कर सकता है?

क्या यह पोस्टमेसेज के अनाज के खिलाफ जा रहा है?

उदाहरण के लिए, यदि मैं कस्टम कॉलबैक को आगे और आगे भेजना चाहता हूं, तो क्या होगा?

+0

सुनिश्चित नहीं है कि आपका क्या मतलब है; आप एक प्राप्त संदेश की जांच करने और सशर्त अलग कोड, आदि को लागू करने के लिए स्वतंत्र हैं, इसलिए ... – Pointy

+0

ऐसा नहीं है कि सिर्फ अब तक है, मैं किसी भी उदाहरण के इस बात का नहीं देखा है, और से मैं क्या पढ़ा है, PostMessage नहीं कर सकते ऑब्जेक्ट्स या कुछ भी भेजें, जिसका मतलब है कि मुझे स्ट्रिंग को विच्छेदन करना होगा ... बस बहुत साफ नहीं लगता है। – johnnietheblack

उत्तर

49

postMessage हैंडलर पर बहु-भाग संदेश पास करने के कुछ तरीके हैं। पहला (और कम "साफ" तरीका) एक डेलीमीटर चरित्र का उपयोग करना है, फिर एक स्ट्रिंग के माध्यम से अपना डेटा पास करें।

मान लें कि हम उपयोगकर्ता आईडी, एक क्रिया, और उपयोगकर्ता नाम पास करना चाहते हैं। स्ट्रिंग इस प्रकार दिखाई देगा:

54|do_logout|chris

postMessage हैंडलर के भीतर, पारित कर दिया डेटा split (docs) | चरित्र पर है, तो संदेश के प्रत्येक खंड के रूप में की जरूरत इस्तेमाल किया जा सकता हो सकता है।

एक और मार्ग के बजाय मैन्युअल रूप से बनाने/एक स्ट्रिंग बंटवारे की, JSON (docs) का उपयोग एक तरफ एक स्ट्रिंग में एक वस्तु कन्वर्ट करने के लिए, और JSON का उपयोग हैंडलर में एक वस्तु को वापस परिवर्तित करने के लिए है।

var pass_data = { 
    'name':'Chris', 
    'id':54, 
    'action':'do_logout' 
}; 
target_window.postMessage(JSON.stringify(pass_data), "http://www.example.net"); 

... तो हैंडलर में:

function (event) { 
    var pass_data = JSON.parse(event.data); 
} 

रूप JSON वस्तु सभी उपयोगकर्ता एजेंटों, विशेष रूप से पुराने लोगों पर प्रदान नहीं की है, परीक्षण करने के लिए सुनिश्चित करें, हालांकि। JSON समर्थन को झुकाव के लिए वहां कई (कई, कई) तृतीय-पक्ष पुस्तकालय हैं, इसलिए पूर्ण गोद लेने की कमी को दूर करने की अनुमति न दें - जेएसओएन निश्चित रूप से एक सुरक्षित "आगे बढ़ने वाला" मानक है।

क्या यह अच्छा नहीं होगा अगर हम उस ऑब्जेक्ट को सीधे पास कर सकें? खैर, फ़ायरफ़ॉक्स 6 (source) में घूमते हुए, जो डेटा आप पोस्टमेसेज हैंडलर को पास करते हैं वह एक ऑब्जेक्ट हो सकता है। वस्तु श्रृंखलाबद्ध किया जाएगा, तो वहाँ उस मोर्चे पर कुछ चिंताएं हैं, लेकिन:

var pass_data = { 
    'name':'Chris', 
    'id':54, 
    'action':'do_logout' 
}; 
target_window.postMessage(pass_data, "http://www.example.net"); 

एक छोटी सी अच्छे, हाँ? दुर्भाग्य से, IE के वर्तमान संस्करण केवल तारों से निपटेंगे। मैं आईई 10 के लिए postMessage के बारे में भविष्य की योजनाओं पर कोई चर्चा नहीं पा रहा था। इसके अलावा, आईई 8/9 में एक ज्ञात बग है जो फ्रेम के अलावा किसी अन्य चीज़ के लिए postMessage तोड़ता है। (source)।

आपके प्रश्न के एक विशिष्ट पहलू में शामिल होना - कॉलबैक। जब तक आप फ़ंक्शन नाम से कॉलबैक पास नहीं कर पा रहे हैं, तब तक कोई फ़ंक्शन पास करने का कोई तरीका नहीं है; आपके लिए कोई अज्ञात कार्य नहीं है। यह वास्तव में हैंडलर पर डेटा को पारित करने के तरीके से संबंधित है। प्रैक्टिस में, ऑब्जेक्ट्स के लिए डेटा के रूप में "नहीं" समर्थन है, दृश्यों के पीछे ब्राउज़र आपके पास ऑब्जेक्ट को एक स्ट्रिंग (क्रमबद्धता) में बदल रहा है।

सब ने कहा, तो, आप को समझना चाहिए कि एक वस्तु गुजर वास्तव में पार करने से पहले एक वस्तु stringify को JSON का उपयोग कर के रूप में एक ही है, केवल पूर्व के मामले ब्राउज़र अपने स्वयं के क्रमबद्धता (और बाद में unserialization) कर रहा है में है, जबकि बाद के मार्ग के साथ आप serialize/unserialize करने के लिए आप पर निर्भर है।

ले दूर यहाँ अंक:

  • postMessage अभी भी सीमित है पार ब्राउज़र समर्थन
  • मानकों का अनुपालन करने ब्राउज़रों के नए संस्करणों के लिए प्रवृत्ति तार
  • के अलावा वस्तुओं के पारित होने की अनुमति देना है
  • पास ऑब्जेक्ट को क्रमबद्ध किया जाएगा, इसलिए कोई फ़ंक्शन संदर्भ
  • सबसे बड़ा समर्थन "जंगली में" स्ट्रिंग-केवल डेटा के लिए है, जिसका अर्थ है कि आपको ऊपर दिखाए गए अनुसार अपने डेटा को स्ट्रिंग और "पैक" करना होगा अगर आप aw का समर्थन करना चाहते हैं उपयोगकर्ता एजेंटों की आईडीई विविधता (परिवार छुट्टियों सहित)

प्रलेखन और संदर्भ

+5

महान जवाब! इच्छा है कि परिवार की छुट्टियों के लिए +10 होगा – johnnietheblack

+1

आप हमेशा जेएसओएन एनकोड और संदेश के दोनों तरफ डीकोड कर सकते हैं। – Pointy

+1

जेएसओएन क्रमबद्धता के साथ भी, आप फ़ंक्शन संदर्भ (जो मुझे विश्वास है कि ओपी बाद में था) पास नहीं कर सकता है क्योंकि उन्हें क्रमबद्ध नहीं किया जा सकता है। यह मामला दोनों है यदि आप JSON ऑब्जेक्ट को एन्कोड करते हैं (IE के लिए) या बस ऑब्जेक्ट पास करें (फ़ायरफ़ॉक्स> 6 के लिए)। आप Firefox में एक समारोह पारित करने के लिए प्रयास करेंगे तो आपको त्रुटि मिलती है 'त्रुटि: वस्तु cloned.' नहीं किया जा सका :(बहुत खराब है, लेकिन हो सकता है यह सुरक्षित –

1

एक बहुत आसान तरीका ट्रिगर करने के लिए कॉलबैक होगा:

लक्ष्य

var callbacks = { 
    myCallback: function() { doSomething(); } 
}; 
window.addEventListener('message', function (ev) { 
    // origin checking etc 
    callbacks[ev.data](); 
}, false); 

स्रोत postMessage साथ

target.postMessage('myCallback', 'http://www.example.com'); 
3

कॉलबैक: बहुत संभव और बहुत उपयोगी

मैं npm called "silver-bullet" पर मिल गया है एक अच्छा प्लगइन है। यह कॉलबैक के साथ पोस्ट मैसेज करता है और विशिष्ट घटनाओं को प्राप्त करने के लिए eventEmitter का भी उपयोग करता है। यह बहुत अच्छा है।

इस तरह मैं कुछ करना होगा लागू करने के लिए लेकिन ...

phostMessage(iframe, someObj, callback); 

आप ऐसा करने के लिए है:

  1. आप एक आम कॉलबैक आईडी संवाद स्थापित करने फ्रेम के बीच पारित कर दिया की जरूरत है।
  2. इस भेजने के बाद कॉलबैक लगाने के लिए प्रत्येक संदेश और एक कॉलबैक देखने हैश में यह भंडार पर एक अद्वितीय कॉलबैक आईडी पैदा करता है।
  3. संदेश के रिसीवर केवल कॉलबैक आईडी को वापस भेज दिया गया है।
  4. सभी इस के लिए एक ही जे एस पुस्तकालय का उपयोग संवाद स्थापित करने फ्रेम शामिल हैं।

    var callbacks = {}; 
    
    // when receiving messages 
    window.addEventListener('message', function(ev) { 
        // todo: add origin check 
        if (!ev.data) 
        return; 
    
        var message; 
        try { 
        message = JSON.parse(ev.data); 
        } catch (ex) { 
        console.error(ex); 
        } 
    
        // ignore messages not having a callback ID 
        if (!message || !message.callbackId) 
        return; 
    
        // we are the sender getting the callback 
        if (callbacks[message.callbackId]) { 
        callbacks[message.callbackId](message); 
        delete callbacks[message.callbackId]; 
        return; 
        } 
    
        // we are the receiver so we respond with the callback ID 
        // todo: restrict who can receive message (last param) 
        iframe.contentWindow.postMessage(JSON.stringify(message), '*'); 
    }); 
    
    // when sending messages 
    function phostMessage(iframe, obj, callback) { 
        obj.eventId = Math.random(); 
        callbacks[obj.eventId] = callback; 
        // todo: restrict who can receive message (last param) 
        iframe.contentWindow.postMessage(JSON.stringify(obj), '*'); 
    } 
    

    मैं थोड़ा आगे इस अवधारणा को लेने के लिए और संदेश हैंडलर देखने जहां संदेश आह्वान और के लिए एक संदेश पारित करने के लिए वांछित हैंडलर समारोह का नाम है का उपयोग करें:

यहाँ इस बात का एक बहुत ही बुनियादी प्रदर्शन है । संदेश हैंडलर कॉलबैक भी लेता है जब पूरा हो जाता है तो कॉलबैक को आग लगती है। कॉलबैक में मूल पोस्ट संदेश को फिर से प्राप्त कॉलबैक आईडी वापस भेजने का सरल तर्क है।

तो संदेश घटना से निपटने के लिए कोड की अंतिम पंक्ति होगा:

if (messageHandler[message.handler]) 
    messageHandler[message.handler](message, function() { 
    iframe.contentWindow.postMessage(JSON.stringify(message), '*'); 
    }); 
else 
    iframe.contentWindow.postMessage(JSON.stringify(message), '*'); 

जो अतुल्यकालिक सामान होने की अनुमति देता है।

संबंधित मुद्दे