「javascript」postMessageとPromise

デスクトップに貼った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);
};

もっといい方法があったらいいなぁ。




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA