为什么定义一个回调/侦听器函数(异步消息传递,port.on)后不立即设置全局变量? [英] Why isn't a global variable set immediately after defining a callback/listener function (asynchronous messaging, port.on)

查看:161
本文介绍了为什么定义一个回调/侦听器函数(异步消息传递,port.on)后不立即设置全局变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编写Firefox加载项我很新颖。但是,我正在尽我所能。所以,我有这个代码,我从MDN

  var tabs = require(sdk / tabs); 
$ b $ tabs.on('activate',function(tab){
var worker = tab.attach({
contentScript:'self.port.emit(html, ($ message)
});
worker.port.on(html,function(message){
console.log(message)
})
});

当我将其更改为:

  var contentHtml =''; 

var tabs = require(sdk / tabs);
$ b $ tabs.on('activate',function(tab){
var worker = tab.attach({
contentScript:'self.port.emit(html,
worker.port.on(html,function(message){
contentHtml = message
})
});

console.log(contentHtml);

它记录一个空字符串。为什么会这样?



把这个放入变量 contentHtml ?

的正确方法是什么? b $ b

解决方案

有关JavaScript中异步代码的更多详细信息,请参阅:




<它记录一个空字符串。为什么会这样?


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


把这个放到变量 contentHtml


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



你的问题不是功能上如何为 contentHtml 赋值。这不是编写Firefox附加组件的具体问题。你的问题是理解异步编程的流程。

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



我已经重写您的代码,以便更清楚地发生什么情况:

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

函数workerAttachedToTabWhenTabActivated(){
//每次激活一个标签时执行。
//直到那个时候才执行。
self.port.emit(html,document.body.innerHTML);
}

函数receiveHtmlMessageFromWorkerViaPortOn(message){
//只有当我们通过port.on接收到一个名为html的消息时才会执行。
//直到收到这样的消息才执行。

//我们在这里设置contentHtml消息。虽然contentHtml变量是在包含代码的
中定义的,但是在这里设置它并不会对我们有任何好处,因为
//程序的其余部分在执行时已经完成。
contentHtml = message;

//显示我们正在做的设置contentHtml。
console.log(contentHtml收到html消息后:+ contentHtml);


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

//当我们执行下面的语句时,contentHtml仍然是。
//当我们到达这里时,我们设置了一个在
//激活的tab上执行的函数,但是这个代码还没有被执行,因为在
//建立这些监听器和执行这个监听器之间的时间。
console.log(contentHtml设置tab.attach后:+ contentHtml);

正如您应该能够看到的,设置全局变量 contentHtml 消息在这个实例中并没有太多好处,因为执行已经通过语句

  console.log(设置tab.attach之后的contentHtml:+ contentHtml); 

由时间 contentHtml 设置为消息。将全局变量 contentHtml 设置为消息只会有一些好处,如果有其他异步代码可能在稍后执行这是希望知道最近收到的 html 消息是什么。



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


I am very new to writing Firefox add-ons. But, I am trying my best. So, I have this code, which I got from MDN:

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)
  })
});

When I change it to:

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);

It logs an empty string. Why is that?

What is the proper way of putting this into the variable contentHtml?

解决方案

For more detailed discussion about asynchronous code in JavaScript see:

It logs an empty string. Why is that?

Because you set contentHtml = '';. At the time that you console.log(contentHtml);, it has not changed.

What is the proper way of putting this into the variable contentHtml?

The way you are doing it assigns it into contentHtml just fine.

Your issue is not functionally how to assign a value to contentHtml. It is not an issue specific to writing a Firefox add-on. Your issue is understanding the flow of asynchronous programming.

JavaScript tends to be written with unnamed functions defined inline where they are used. While this is more compact, I find that it tends to result in newer programmers not as readily understanding the execution flow of a program that is asynchronous.

I have re-written your code so it is more clear as to what happens when:

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);

As you should be able to see, setting the global variable contentHtml to the message does not do much good in this instance because execution has already passed the statement

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

by the time contentHtml is set to the message. Setting the global variable contentHtml to the message would only do some good if there were other asynchronous code which might execute later in which it was desired to know what the most recent html message that had been received was.

In general, everything that depends on the contents of the html message should be put in the function that is executed when that message is received.

这篇关于为什么定义一个回调/侦听器函数(异步消息传递,port.on)后不立即设置全局变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆