zoukankan      html  css  js  c++  java
  • 编写你的应用程序(七)、消息系统

    原文链接:https://developer.chrome.com/native-client/devguide/coding/message-system

    注意:已针对ChromeOS以外的平台公布了此处所述技术的弃用。
    请访问我们的 迁移指南 了解详情。


    消息系统

    本节介绍用于在Native Client应用程序中的JavaScript代码与Native Client模块的C或C ++代码之间进行通信的消息传递系统。它介绍了异步编程的概念以及设置向JavaScript发送消息和从JavaScript接收消息的Native Client模块所需的基本步骤。本节假定您熟悉“ 应用程序结构”部分中提供的材料 。

    这里使用“Hello,World”开始使用NaCl的示例来说明基本的编程技术。您可以/getting_started/part2在Native Client SDK下载的目录中找到此代码。

    参考信息

    有关Pepper消息传递API的参考信息,请参阅以下文档:

    邮件系统简介

    Native Client模块和JavaScript通过相互发送消息进行通信。消息的最基本形式是字符串。消息支持许多JavaScript类型,包括int,数组,数组缓冲区和字典(请参阅 pp :: Var, pp:VarArrayBuffer和常规消息传递系统文档)。由您决定消息类型并定义如何在JavaScript和Native Client端处理消息。对于“Hello,World”示例,我们仅使用字符串类型的消息。

    当JavaScript将消息发布到Native Client模块时,HandleMessage()会在模块端调用Pepper 函数。类似地,Native Client模块可以将消息发布到JavaScript,此消息会触发messageDOM中事件的JavaScript事件侦听器 。(有关更多信息,请参阅文档对象模型事件的W3C规范 。)在“Hello,World”示例中,用于发布和处理消息的JavaScript函数已命名postMessage()并且 handleMessage()(但可以使用任何名称)。在Native Client C ++端,用于发布和处理消息的Pepper Library函数是:

    • void pp::Instance::PostMessage(const Var &message)
    • virtual void pp::Instance::HandleMessage(const Var &message)

    如果要从JavaScript接收消息,则需要pp::Instance::HandleMessage()在Native Client模块中实现该 功能。

    消息系统的设计

    Native Client消息传递系统类似于浏览器允许Web工作者进行通信的系统(请参阅W3 Web工作者规范)。Native Client消息传递系统旨在使Native Client模块在后台执行可能繁重的处理时保持Web页面响应。当JavaScript向Native Client模块发送消息时,一旦将消息发送到Native Client模块,该postMessage()调用就会返回。JavaScript不会等待Native Client的回复,从而避免陷入主JavaScript线程。在JavaScript方面,您设置了一个事件侦听器,以响应Native Client模块完成请求的处理并返回消息时发送的消息。

    此异步处理模型使主线程保持空闲,同时避免以下问题:

    • JavaScript引擎在等待同步调用返回时挂起。
    • 当JavaScript入口点花费的时间超过一些时,浏览器会弹出一个对话框。
    • 应用程序在等待无响应的Native Client模块时挂起。

    “Hello,World”示例中的通信任务

    以下部分描述了“Hello,World”示例如何在应用程序的JavaScript端和Native Client端发布和处理消息。

    JavaScript代码

    JavaScript代码和HTML中的“你好,世界”的例子可以在发现example.jscommon.jsindex.html文件。重要的步骤是:

    1. 设置事件侦听器以侦听messageNative Client模块中的事件。
    2. 实现事件处理程序调用以处理传入message事件的事件处理程序。
    3. postMessage()在页面加载后调用与NaCl模块通信。

    第1步:来自common.js

    function attachDefaultListeners() {
      // The NaCl module embed is created within the listenerDiv
      var listenerDiv = document.getElementById('listener');
      // ...
    
      // register the handleMessage function as the message event handler.
      listenerDiv.addEventListener('message', handleMessage, true);
      // ...
    }

    第2步:来自example.js

    // This function is called by common.js when a message is received from the
    // NaCl module.
    function handleMessage(message) {
      // In the example, we simply log the data that's received in the message.
      var logEl = document.getElementById('log');
      logEl.textContent += message.data;
    }
    
    // In the index.html we have set up the appropriate divs:
    <body {attrs}>
      <!-- ... -->
      <div id="listener"></div>
      <div id="log"></div>
    </body>

    第3步:来自example.js

    // From example.js, Step 3:
    function moduleDidLoad() {
      // After the NaCl module has loaded, common.naclModule is a reference to the
      // NaCl module's <embed> element.
      //
      // postMessage sends a message to it.
      common.naclModule.postMessage('hello');
    }

    Native Client模块

    “Hello,World”示例的Native Client模块中的C ++代码:

    1. 实现pp::Instance::HandleMessage()处理JavaScript发送的消息。
    2. 处理传入的消息。此示例仅检查JavaScript是否已发送“hello”消息而不是其他消息。
    3. 调用PostMessage()将确认发送回JavaScript代码。确认是VarJavaScript代码可以处理的字符串形式。通常,a pp::Var可以是多种JavaScript类型,请参阅消息传递系统文档
      class HelloTutorialInstance : public pp::Instance {
       public:
        // ...
      
        // === Step 1: Implement the HandleMessage function. ===
        virtual void HandleMessage(const pp::Var& var_message) {
      
          // === Step 2: Process the incoming message. ===
          // Ignore the message if it is not a string.
          if (!var_message.is_string())
            return;
      
          // Get the string message and compare it to "hello".
          std::string message = var_message.AsString();
          if (message == kHelloString) {
            // === Step 3: Send the reply. ===
            // If it matches, send our response back to JavaScript.
            pp::Var var_reply(kReplyString);
            PostMessage(var_reply);
          }
        }
      };

    JavaScript代码中的消息传递:更多详细信息。

    本节更详细地描述了“Hello,World”示例的JavaScript部分中的消息传递系统代码。

    设置事件侦听器和处理程序

    以下JavaScript代码为Native Client模块发布的消息设置事件侦听器。然后,它定义了一个消息处理程序,它只记录从模块接收的消息内容。

    在加载时设置'message'处理程序

    // From common.js
    
    // Listen for the DOM content to be loaded. This event is fired when
    // parsing of the page's document has finished.
    document.addEventListener('DOMContentLoaded', function() {
      var body = document.body;
      // ...
      var loadFunction = common.domContentLoaded;
      // ... set up parameters ...
      loadFunction(...);
    }
    
    // This function is exported as common.domContentLoaded.
    function domContentLoaded(...) {
      // ...
      if (common.naclModule == null) {
        // ...
        attachDefaultListeners();
        // initialize common.naclModule ...
      } else {
        // ...
      }
    }
    
    function attachDefaultListeners() {
      var listenerDiv = document.getElementById('listener');
      // ...
      listenerDiv.addEventListener('message', handleMessage, true);
      // ...
    }

    实现处理程序

    // From example.js
    function handleMessage(message) {
      var logEl = document.getElementById('log');
      logEl.textContent += message.data;
    }

    请注意,该handleMessage()函数将传递一个message_event,其中包含data您可以在JavaScript中显示或操作的内容。“Hello,World”应用程序只是将此数据记录到logdiv中。

    Native Client模块中的消息传递:更多详细信息。

    本节更详细地描述了“Hello,World”示例的Native Client模块部分中的消息传递系统代码。

    实现HandleMessage()

    如果希望Native Client模块接收和处理来自JavaScript的消息,则需要HandleMessage()为模块的pp::Instance类实现一个函数。该 HelloWorldInstance::HandleMessage()函数检查从JavaScript发布的消息。首先,它检查它的类型 pp::Var确实是一个字符串(不是双重等)。然后它将数据解释为带有的字符串var_message.AsString(),并检查字符串是否匹配kHelloString。在检查从JavaScript接收的消息之后,代码调用PostMessage()将回复消息发送回JavaScript端。

    namespace {
    
    // The expected string sent by the JavaScript.
    const char* const kHelloString = "hello";
    // The string sent back to the JavaScript code upon receipt of a message
    // containing "hello".
    const char* const kReplyString = "hello from NaCl";
    
    }  // namespace
    
    class HelloTutorialInstance : public pp::Instance {
     public:
      // ...
      virtual void HandleMessage(const pp::Var& var_message) {
        // Ignore the message if it is not a string.
        if (!var_message.is_string())
          return;
    
        // Get the string message and compare it to "hello".
        std::string message = var_message.AsString();
        if (message == kHelloString) {
          // If it matches, send our response back to JavaScript.
          pp::Var var_reply(kReplyString);
          PostMessage(var_reply);
        }
      }
    };

    实现特定于应用程序的功能

    虽然“Hello,World”示例非常简单,但Native Client模块可能包含特定于应用程序的函数,以执行自定义任务以响应消息。例如,应用程序可以是压缩和解压缩服务(导出两个函数)。应用程序可以设置一个特定于应用程序的约定,来自JavaScript的消息是以冒号分隔的形式对<command>:<data>。然后,Native Client模块消息处理程序可以沿着:字符拆分传入的字符串,以确定要执行的命令。如果命令是“compress”,则要处理的数据是未压缩的字符串。如果命令是“uncompress”,则要处理的数据是已经压缩的字符串。在异步处理数据之后,应用程序然后将结果返回给JavaScript。

    将消息发送回JavaScript代码

    Native Client模块使用以下命令将消息发送回JavaScript代码PostMessage()。Native Client模块始终pp::Var以可由浏览器的JavaScript处理的形式返回其值。在此示例中,消息在Native Client模块的HandleMessage()功能结束时发布:

    PostMessage(var_reply);

    发送和接收其他pp::Var类型

    除了字符串,pp::Var还可以表示其他类型的JavaScript对象。例如,消息可以是JavaScript对象。这些更丰富的类型可以更容易地实现应用程序的消息传递协议。

    要将NaCl模块中的字典发送到JavaScript,只需创建一个pp::VarDictionary然后PostMessage使用字典调用。

    pp::VarDictionary dictionary;
    dictionary.Set(pp::Var("command"), pp::Var(next_command));
    dictionary.Set(pp::Var("param_int"), pp::Var(123));
    pp::VarArray an_array;
    an_array.Set(0, pp::Var("string0"));
    an_array.Set(1, pp::Var("string1"))
    dictionary.Set(pp::Var("param_array"), an_array);
    PostMessage(dictionary);

    以下是如何在JavaScript中创建类似对象并将其发送到NaCl模块:

    var dictionary = {
      command: next_command,
      param_int: 123,
      param_array: ['string0', 'string1']
    }
    nacl_module.postMessage(dictionary);

    要在NaCl模块中接收字典类型的消息,请测试该消息是否真的是字典类型,然后使用pp::VarDictionary该类转换消息。

    virtual void HandleMessage(const pp::Var& var) {
      if (var.is_dictionary()) {
        pp::VarDictionary dictionary(var);
        // Use the dictionary
        pp::VarArray keys = dictionary.GetKeys();
        // ...
      } else {
        // ...
      }
    }

    CC-By 3.0许可下提供的内容

  • 相关阅读:
    如何有效阅读一本书:超实用笔记读书法
    typescript 为什么使用 let呢
    typescript step by step
    typescript 第一弹
    oracle 闪回操作(flashback)
    oracle自动备份
    将Tomcat添加至开机自启动
    svg 鼠标形状 小手
    jquery 多个checkbox的联动选择
    java中奇偶数的判断
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049127.html
Copyright © 2011-2022 走看看