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许可下提供的内容

  • 相关阅读:
    LeetCode Array Easy 414. Third Maximum Number
    LeetCode Linked List Medium 2. Add Two Numbers
    LeetCode Array Easy 283. Move Zeroes
    LeetCode Array Easy 268. Missing Number
    LeetCode Array Easy 219. Contains Duplicate II
    LeetCode Array Easy 217. Contains Duplicate
    LeetCode Array Easy 189. Rotate Array
    LeetCode Array Easy169. Majority Element
    LeetCode Array Medium 11. Container With Most Water
    LeetCode Array Easy 167. Two Sum II
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049127.html
Copyright © 2011-2022 走看看