Nix*_*n85 5 javascript iframe postmessage promise async-await
我有一个iframe,它正在与其父窗口进行通信以通过postMessage 方法设置和获取一些必要的cookie 。
首先,iframe应用程序中的一个函数从父窗口请求CookieA。
function requestCommunication(topic, customerId) {
function cookieAvailable() {
return new Promise((resolve) => resolve(getCookieData('cookieName'));
});
}
console.log(cookieAvailable());
if(!!cookieAvailable()) {
//doStuff
}
}
Run Code Online (Sandbox Code Playgroud)
cookieAvailable()触发从iframe发送到parent.window的消息。依次,窗口返回cookie及其数据作为字符串。通过使用以下操作完成此操作:
async function getCookieData(cookieName) {
const {data} = await new Promise(resolve => {
window.onmessage = (event) => {
resolve(event);
}
});
var cookieContent = JSON.parse(data);
var cookieContentData = JSON.parse(cookieContent.data);
return cookieContentData; //this returns the cookie data (in almost all cases)
}
Run Code Online (Sandbox Code Playgroud)
我没有如何正确使用诺言将其移交给我的初始触发功能。我将不胜感激。
您的代码中存在明显的问题和反模式。cookieAvailable将返回一个 Promise,因此您的支票if(!!cookieAvailable()) {将始终是真实的。在检查是否确实有可用的 cookie 之前,您需要等待该 Promise 解决。
但实际上,你的cookieAvailable函数没有任何返回 Promise 包装器:如果thisChatClient.cookie.getCookieData返回 Promise 则直接返回它,无需将其包装在 Promise 中。
如果它返回一个同步结果,那么你只能通过将其包装在 Promise 中来释放它
async function requestCommunication(topic, customerId) {
function cookieAvailable() {
// this is already a Promise
return thisChatClient.cookie.getCookieData('sess_au');
}
const isCookieAvailable = await cookieAvailable();
if (!!isCookieAvailable) {
}
}
requestCommunication().catch(console.error);
Run Code Online (Sandbox Code Playgroud)
现在所有这些都无助于对您的问题做出正确的回答:您的两个代码块之间的链接根本不清楚。
没有任何东西调用这两个函数。
您getCookieData将等待一个 MessageEvent,而不让任何人知道它正在等待它。
我不确定您打算如何让您的 iframe 知道它应该向您的窗口发送一条包含此信息的消息,但这是您必须考虑的事情。
但在去那里之前我应该注意:尽管它可能很诱人,但将事件包装在 Promise 中通常是一个坏主意。
事件和承诺是不同的东西,后者应该只解决一次,而前者可能会从不同的来源多次触发。
IMM 只有当您确定事件只会触发一次时才最好这样做。对于 MessageEvent,您根本不知道它。
您的用户很可能在其浏览器上安装了一个扩展程序,该扩展程序将使用 postMessage 作为通信方式。如果在所有 iframe 上添加此扩展,则您的代码将被破坏。
相反,您应该检查MessageChannel API,它将为您提供通信方式,您可以确定您将是唯一使用的通信方式。
我认为这个答案不适合解释这个 API 是如何工作的,但是请看一下这个概述,它解释了非常基础的知识。
由于您一定会控制两端,因此您可以从那里建立一个基于 Promise 的系统。
在主页中,您将准备 MessageChannel 对象,并将其发送到 iframe,同时侦听响应。当这个响应到来时,你将能够实现你的 Promise。
在 iframe 中,您将在窗口上添加一个侦听器以捕获 MessageChannelPort。发生这种情况时,您将向服务请求 cookie 并通过 MessageChannel 的端口将其发回。
即使在这次交换期间主窗口上出现一条消息,您也可以确定它不会是您正在等待的消息。
// Sets up a new MessageChannel
// so we can return a Promise
function getCookieData() {
return new Promise((resolve) => {
const channel = new MessageChannel();
// this will fire when iframe will answer
channel.port1.onmessage = e => resolve(e.data);
// let iframe know we're expecting an answer
// send it its own port
frame.contentWindow.postMessage('getCookie', '*', [channel.port2]);
});
}
frame.onload = async e => {
const frameHasCookie = await getCookieData();
console.log(frameHasCookie);
};
frame.src = generateFrameSRC();
function generateFrameSRC() {
// The content of your iframe
const cont = `
<html>
<head>
<script>
const originClean = "null";
onmessage = async e => {
// only if it's the origin we expected
// and if it does send a MessagePort
// and the message is "getCookie"
if(e.origin === originClean && e.ports && e.data === "getCookie") {
const data = await asyncData();
// respond to main window
e.ports[0].postMessage(data);
}
};
function asyncData() {
return new Promise(resolve =>
setTimeout(() => resolve("the data"), 1000)
);
}
<\/script>
</head>
<body>
hello
</body>
</html>`;
return 'data:text/html,' + encodeURIComponent(cont)
}Run Code Online (Sandbox Code Playgroud)
<iframe id="frame"></iframe>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
562 次 |
| 最近记录: |