デスクトップに貼ったJSからSJISのCSVをダウンロードさせてみる【その後】の中で、
iframeへ送信したメッセージの応答をawaitで待機するようにしていますが、postMessageは本当にメッセージをポストするダケの機能なのでレス待ちなんで事ができません。
displayStatus(`サンプルを${encoding}に変換中`);
let unicode16CSV = await getSampleTextInnerText();
タネを明かすと、これを実現するために外部変数messageResponseStackにPromiseのresolveを保持し、どこかで応答メッセージを受信したらresolveを呼び出してawaitの待機状態を解除してもらっています。
つまり職場(プロセス)に居れば誰でも見れるホワイトボード(外部変数)に取引先(requestID)と連絡先(resolve)を書いてあるので、暇になった人が気が付けばかかってきた電話の相手先(requestID)の要件(event.data.message)を連絡してもらえる(ハズ
な仕組みです。
ついでにrequestIDはワンタイムなIDなのでホワイトボードから消してます。
/**
* iframeのサンプルを取得する
* @returns
*/
const getSampleTextInnerText = () => {
return new Promise((resolve, reject) => {
loaderOpen();
var us = getUniqueStr();
messageResponseStack[us] = { 'resolve': resolve, 'reject': reject };
myPostMessage('iframe', "getSampleText", "", us);
});
};
messageProcSetup({ ☚ここでmessageListner の応答メッセージタイプ毎のコールバック先をリストアップ
・・・
'getEncodingListResponse': messageResponseProc,
・・・
});
/**
* メッセージのレスポンス処理 ☚ messageListnerからコールバックされる。
*/
const messageResponseStack = {};
const messageResponseProc = (data) => {
loaderClose();
if (data.requestId !== undefined) {
messageResponseStack[data.requestId].resolve(JSON.parse(data.message));
delete messageResponseStack[data.requestId];
} else {
alert(`not requestId${CRLF}data.type: ${data.type}`);
}
};
/**
* メッセージを受信する
* @param {MessageEvent} event
*/
const messageListner = (event) => {
if (event.origin !== myOriginListener || event.type !== 'message') return;
let data = event.data;
let messageInfo = messageInfoList[data.type];
if (messageInfo === undefined) {
alert(`unkonwn message type = '${data.type}'${CRLF}message: ${data.message}`);
return;
}
if (messageInfo !== undefined && messageInfo !== null) {
if (Array.isArray(messageInfo)) {
if (messageInfo.length > 1) {
messageInfo[0](data, ...(messageInfo.slice(1)));
} else {
messageInfo[0](data);
}
} else {
messageInfo(data);
}
}
};
/**
* メッセージを送信する
* @param {string} textType
* @param {string} textMessage
* @param {string} textRequestId
*/
const myPostMessage = (to, textType, textMessage, textRequestId) => {
switch (to) {
case 'parent': // 親ドキュメントに送信する
to = window.parent;
break;
case 'iframe': // iframeへメッセージを送信する
to = document.querySelector("iframe").contentWindow;
break;
}
to.postMessage({
type: textType,
message: textMessage,
requestId: textRequestId,
}, myOriginSender);
};
もっといい方法があったらいいなぁ。