タブ間通信


最近の話を非同期JavaScriptについて置くとき、ブラウザのタブを制御することができるブラウザで制御されたプレゼンテーションを構築することを探していました.特に、3つのことを管理しています.
  • のスライド位置
  • スライドフォントサイズ
  • のスライドアクション
  • つ目のスライドアクションでは、コードを実行するのと同様にいくつかのコード(開発者用ツール)コンソールの表示をトリガーしていました.
    長年のフロントエンド開発者として、私はブラウザタブがサンドボックスされていることを知っているが、時間とともにこのタイプの機能を見てきた.しかし、どこに気づかなかった記憶.私はまた、この機能を持っているプレゼンテーションツール(reveal.jsなど)のいくつかを調べてみました.
    私が遭遇したのはブロードキャストチャンネルで、FirefoxとChromeでcaniuse.comにサポートされています.IEやEDGEを使ってプレゼンテーションをしようとしていないので、この素晴らしい情報を考えました.

    セットアップチャンネル
    この機能の使用はかなり簡単です傷.このコードはインデックス内のプロセスを開始しました.JavaScriptのコード.
    const pnChannel = new BroadcastChannel('le-slides-position');
    const fsChannel = new BroadcastChannel('le-slides-font-size');
    const anChannel = new BroadcastChannel('le-slides-actions');
    
    での注意.JSは、サイズのサイジング.JSファイルとRADEコード例ファイルは、一致する宣言です.
    // _navigation.js
    const channel = new BroadcastChannel('le-slides-position');
    
    // _font-sizing.js
    const channel = new BroadcastChannel('le-slides-font-size');
    
    // _code-examples.js
    const channel = new BroadcastChannel('le-slides-actions');
    
    注意:これらの行はそれぞれ別々のファイルになりますので、各行にconst channelを使用します.

    チャネル通信
    ここでは、制御インデックスからデータを送信することを検討します.HTML、機能、JSコード.
    const actions = {
      init: (force = false) => {
        if (!initFired || force) {
          fsChannel.postMessage('init');
          pnChannel.postMessage('init');
          anChannel.postMessage('init');
          initFired = true;
        }
      },
    
      up: () => {
        if (!upButton.hasClass('disabled')) {
          fsChannel.postMessage('trigger-up');              
        }
      },
      reset: () => {
        fsChannel.postMessage('trigger-reset');         
      },
      down: () => {
        if (!downButton.hasClass('disabled')) {
          fsChannel.postMessage('trigger-down');                
        }
      },
    
      previous: () => {
        if (!previousButton.hasClass('disabled')) {
          pnChannel.postMessage('trigger-previous');                
        }
      },
      next: () => {
        if (!nextButton.hasClass('disabled')) {
          pnChannel.postMessage('trigger-next');
        }
      },
    
      triggerAction: (action) => {
        anChannel.postMessage(action);
      }
    };
    

    位置チャネル
    さて、PNChannelを見てください.私たちはそれを見ることができます.OnMessage関数は、状態を予想します.送信される状態にはデータが含まれます.この場合、現在のインデックスは何ですか?また、追加のデータは、前および次の無効状態などの送信され、これらのボタンを適切に調整することができます.
    pnChannel.onmessage = (states) => {
      cardIndex = states.data.currentIndex;
      updateContent();
    
      if (states.data.previousDisabled) {
        previousButton.addClass('disabled');
      } else {
        previousButton.removeClass('disabled');
      }
    
      if (states.data.nextDisabled) {
        nextButton.addClass('disabled');
      } else {
        nextButton.removeClass('disabled');
      }
    };
    
    での注意.JSファイルは、データが実際にいくつかの機能を実行するために使用されるtriggeractionをrecieves.
    channel.onmessage = (triggerAction) => {
      actions[triggerAction.data]();
    };
    
    const actions = {
      init: () => {
        nextButton.hide();
        previousButton.hide();
      },
    
      'trigger-previous': () => {
        slideStateMachine.next('previous');
      },
      'trigger-next': () => {
        slideStateMachine.next('next');
      },
    
      'report-states': (index) => {
        channel.postMessage({
          currentIndex: index,
          previousDisabled: previousButton.hasClass('disabled'),
          nextDisabled: nextButton.hasClass('disabled')
        });
      }
    };
    
    このコードで、メッセージを送ることが単に利用することであることが明らかになるはずです.チャンネルのPostgreSQL機能.

    フォントサイズ設定
    Fschannelを見ることができます.OnMessageは再び状態を予想します.そして、ボタン州が割り当てられるのを許します..
    fsChannel.onmessage = (states) => {
      if(states.data.upDisabled) {
        upButton.addClass('disabled');
      } else {
        upButton.removeClass('disabled');
      }
    
      if(states.data.downDisabled) {
        downButton.addClass('disabled');
      } else {
        downButton.removeClass('disabled');
      }     
    };
    
    これは{*} Count Font -サイジングに接続されています.JS *コードは、再び様々なアクションをトリガします.
    channel.onmessage = (triggerAction) => {
      actions[triggerAction.data]();
    };
    
    const actions = {
      init: () => {
        upButton.hide();
        downButton.hide();
        resetButton.hide();
      },
    
      'trigger-up': () => {
        fontStateMachine.next('up');
      },
      'trigger-reset': () => {
        fontStateMachine.next('reset');      
      },
      'trigger-down': () => {
       fontStateMachine.next('down');
      },
    
      'report-states': () => {
        channel.postMessage({
          upDisabled: upButton.hasClass('disabled'),
          downDisabled: downButton.hasClass('disabled')
        });
      }
    };
    

    アクションチャンネル
    ここで、応答状態データは単にコンソールに送られます.ログ.
    anChannel.onmessage = (states) => {
      console.log('action reply:', states.data);
    };
    
    剰余コード例の関連コード.JSファイルはもう少し複雑です.
    channel.onmessage = (states) => {
      const cardAction = cardActions[states.data];
      if (states.data === 'init') {
        cardAction();
      } else {
        if (cardAction.showDisplay) {
          console.log(cardAction.display);      
        }
        cardAction.fn();        
      }
    };
    
    この場合、私は特定の目的のために少し「騙される」ことを認めます.私はいくつかのJSONデータを使用しました.
    "fn": "triggerImage('queues.png', false)"
    
    ... そして、剰余コードの例の範囲内で.JS init機能、実行機能として再構築します.したがって、私はJSONファイルを使用して、各画面の要素を制御することができました.
    const name = card.options[j].name;
    const optionFn = new Function(card.options[j].fn);
    cardActions[name] = {
      fn: optionFn,
      showDisplay: card.options[j].showFn,
      display: card.options[j].fn
    };
    

    結論
    私はプロジェクトでエキサイティングなことをたくさん学びました.私はむしろ直接それを与えるしないので、私はここにそれをリンクするつもりはない.
    私の記事の内容は私がSingle-Threaded and Asynchronous JavaScript?に提示するものです.
    これは面白いプロジェクトでしたし、ある時点で、私は自分自身のプレゼンテーションに、この作業を見ることができます.