为什么在定义回调/侦听器函数后不立即设置全局变量(异步消息传递,port.on)

时间:2016-03-21 13:51:32

标签: javascript asynchronous firefox-addon firefox-addon-sdk

我是编写Firefox附加组件的新手。但是,我正在努力。所以,我有这个代码,我got from MDN

cd <path_to_your_app_root>    
sencha app upgrade <path_to_extjs_root_folder>

当我将其更改为:

var tabs = require("sdk/tabs");

tabs.on('activate', function(tab) {
  var worker = tab.attach({
    contentScript: 'self.port.emit("html", document.body.innerHTML);'
  });
  worker.port.on("html", function(message) {
   console.log(message)
  })
});

它记录一个空字符串。那是为什么?

将此项放入变量var contentHtml = ''; var tabs = require("sdk/tabs"); tabs.on('activate', function(tab) { var worker = tab.attach({ contentScript: 'self.port.emit("html", document.body.innerHTML);' }); worker.port.on("html", function(message) { contentHtml = message }) }); console.log(contentHtml); 的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

有关JavaScript中异步代码的更详细讨论,请参阅:

  

它记录一个空字符串。那是为什么?

因为您设置了contentHtml = '';。在您console.log(contentHtml);时,它没有改变。

  

将此项放入变量contentHtml的正确方法是什么?

你这样做的方式将它分配到contentHtml就好了。

您的问题不在于如何为contentHtml分配值。这不是特定于编写Firefox附加组件的问题。您的问题是了解异步编程的流程。

JavaScript往往使用内联定义的未命名函数编写,使用它们。虽然这更紧凑,但我发现它往往会导致较新的程序员不能轻易理解异步程序的执行流程。

我已经重新编写了代码,以便在以下情况下更清楚:

var tabs = require("sdk/tabs");
var contentHtml = '';

function workerAttachedToTabWhenTabActivated() {
    //This is executed every time a tab is activated.
    //It is not executed until that time.
    self.port.emit("html", document.body.innerHTML);
}

function receiveHtmlMessageFromWorkerViaPortOn(message) {
    //This is executed only when we receive a message via port.on that is named "html".
    //It is not executed until such a message is received.

    //We set contentHtml to message here. While the contentHtml variable is defined in the
    //  containing code, setting it here does not, currently, do us any good because
    //  the rest of the program has already completed by the time this is executed.
    contentHtml = message;

    //Show that we actualy do set contentHtml.
    console.log("contentHtml after receiving html message:" + contentHtml);
}

tabs.on('activate', function(tab) {
  var worker = tab.attach({
    contentScript: 'workerAttachedToTabWhenTabActivated();'
  });
  worker.port.on("html", receiveHtmlMessageFromWorkerViaPortOn(message))
});

//When we execute the following statement contentHtml is still "".
//When we get here, we have set up our functions that are executed upon a tab becoming
//active, but that code has not yet been executed because no tab became active in the small
//amount of time between setting up those listeners and this executing.
console.log("contentHtml after setting up tab.attach:" + contentHtml);

正如您应该看到的那样,将全局变量contentHtml设置为message在此实例中没有太大作用,因为执行已经通过了语句

console.log("contentHtml after setting up tab.attach:" + contentHtml);

时{p}设置为contentHtml。将全局变量message设置为contentHtml只会有一些好处,如果有其他异步代码可能会在以后执行,希望知道最新的message {{1收到的是。

通常,依赖于html message内容的所有内容都应放在收到该消息时执行的函数中。