加入收藏 | 设为首页 | 会员中心 | 我要投稿 武汉站长网 (https://www.027zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 移动互联 > 应用 > 正文

编写你的应用程序(七)、消息系统

发布时间:2023-01-12 11:31:27 所属栏目:应用 来源:未知
导读: 消息系统
本节介绍用于在Native Client应用程序中的JavaScript代码与Native Client模块的C或C ++代码之间进行通信的消息传递系统。它介绍了异步编程的概念以及设置向JavaScript发送消息和从

消息系统

本节介绍用于在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函数是:

如果要从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模块完成请求的处理并返回消息时发送的消息。

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

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

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

JavaScript代码

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

设置事件侦听器以侦听messageNative Client模块中的事件。实现事件处理程序调用以处理传入message事件的事件处理程序。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:

  
  

第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  element.
  //
  // postMessage sends a message to it.
  common.naclModule.postMessage('hello');
}

Native Client模块

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

实现pp::Instance::HandleMessage()处理JavaScript发送的消息。处理传入的消息。此示例仅检查JavaScript是否已发送“hello”消息而不是其他消息。调用PostMessage()将确认发送回JavaScript代码。确认是VarJavaScript代码可以处理的字符串形式。通常,app::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的消息是以冒号分隔的形式对:。然后,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许可下提供的内容

(编辑:武汉站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章