卸载事件页面后,chrome 上的 UDP 套接字未获得 onReceive 回调
Not getting onReceive callback for UDP socket on chrome after event page is unloaded
我正在创建一个 chrome 应用程序(已打包),我必须创建一个 UDP 套接字并在 chrome 浏览器启动后立即侦听传入的广播消息。
启动浏览器时一切正常,我通过 chrome.sockets.udp.onReceive.addListener()
API 和数据注册了回调。
事件页面卸载时(大约 10-15 秒后)问题开始出现。
未收到任何新的 UDP 数据包。
但如 Chrome Apps & Extensions Developer Tool
所示,onReceive
回调触发 一次 即使在事件页面被卸载后(但不是对于后续的 UDP 数据包),但是它没有命中我的回调函数。
并且我在创建 UDP 套接字时将 persistent
标志保持为真。
这是我的应用程序清单:
{
"manifest_version": 2,
"name": "App Name",
"description": "Description",
"version": "1.0",
"app": {
"background": {
"scripts": ["socket.js","eventPage.js"],
"persistent": true
}
},
"sockets":{
"udp": {"send":["*:*"], "bind":["*:*"]}
},
"permissions":["system.network","notifications"]
}
活动页面和套接字代码:
// eventPage.js
chrome.runtime.onStartup.addListener(function() {
console.log("I started up!");
socket.cleanup_create();
});
chrome.runtime.onSuspend.addListener(function() {
console.log("I am being suspended!");
});
// socket.js
function show(jsontext) {
var json_object = JSON.parse(jsontext);
console.log(json_object.TitleText);
console.log(json_object.MainText);
chrome.notifications.create("",
{type:'basic',iconUrl:'icon.png',title:json_object.TitleText,message:json_object.MainText},
function callback(){})
}
var socket = {
socketId:null,
/*==========Receive Callback=================*/
recieve_callback:function(rc){
console.log("Received on socket ID "+rc.socketId);
var dataView = new DataView(rc.data);
var decoder = new TextDecoder("utf-8");
var decodedString = decoder.decode(dataView);
console.log("Data Received and it is "+decodedString);
show(decodedString);
},
/*==========Receive Error Callback=================*/
recieve_error_callback:function(info){
console.log("Error on socket with code "+info.resultCode);
},
/*==========Bind Callback=================*/
bind_cb: function(s){
console.log("Socket seems to be binded result "+s);
chrome.sockets.udp.onReceive.addListener(socket.recieve_callback)
chrome.sockets.udp.onReceiveError.addListener(socket.recieve_error_callback)
},
/*==========Create Callback=================*/
create_cb: function(s){
console.log("Socket seems to be created id is "+s.socketId);
socket.socketId = s.socketId;
chrome.sockets.udp.bind(socket.socketId,"0.0.0.0",8080,socket.bind_cb);
},
/*==========Create Method=================*/
create: function(){
chrome.sockets.udp.create({persistent:true,name:"udp_socket",bufferSize:15000},socket.create_cb);
},
cleanup_create:function(){
chrome.sockets.udp.getSockets(function cleanup_create_cb(socketInfos){
console.log("Cleaning up existing sockets "+socketInfos.length);
for (i = 0; i < socketInfos.length; i++) {
chrome.sockets.udp.close(socketInfos[i],function socket_close_cb(){});
}
socket.create();
});
}
};
有什么方法可以让活动页面始终处于加载状态,或者有什么其他方法可以确保我始终获得 onReceive
活动吗?
Chrome 活动页面如何运作?这里是 the documentation,但简而言之:
- 执行您页面的顶级上下文,为事件注册侦听器。
- Chrome 构建一个应该唤醒页面的事件列表。
- 页面卸载:请注意,它完全破坏了 JS 上下文,包括侦听器 和任何已初始化的对象(例如您的
socket
对象)。
- 事件发生。 Chrome 查找是否需要唤醒您的页面。假设是这样。
- 页面再次加载,侦听器再次注册,然后Chrome调用它们。
引用文档:
Because the listeners themselves only exist in the context of the event page, you must use addListener
each time the event page loads; only doing so at runtime.onInstalled
by itself is insufficient.
现在让我们看看这一行:
// Called in a callback to chrome.sockets.udp.bind()
bind_cb: function(s){
/* ... */
chrome.sockets.udp.onReceive.addListener(socket.recieve_callback)
/* ... */
}
再次加载页面时,这不会同步执行。因此,在第 5 步,Chrome 找不到合适的侦听器,因此未被调用。
请注意事件是全局的,即它没有绑定到套接字对象(卸载后不存在)。因此,您可以(并且应该)安全地将它绑定到一个分析回调参数的函数,以了解它在哪个套接字上运行。
因此,要使您的代码正常工作,addListener
必须 在事件页面加载时同步调用。
我正在创建一个 chrome 应用程序(已打包),我必须创建一个 UDP 套接字并在 chrome 浏览器启动后立即侦听传入的广播消息。
启动浏览器时一切正常,我通过 chrome.sockets.udp.onReceive.addListener()
API 和数据注册了回调。
事件页面卸载时(大约 10-15 秒后)问题开始出现。
未收到任何新的 UDP 数据包。
但如 Chrome Apps & Extensions Developer Tool
所示,onReceive
回调触发 一次 即使在事件页面被卸载后(但不是对于后续的 UDP 数据包),但是它没有命中我的回调函数。
并且我在创建 UDP 套接字时将 persistent
标志保持为真。
这是我的应用程序清单:
{
"manifest_version": 2,
"name": "App Name",
"description": "Description",
"version": "1.0",
"app": {
"background": {
"scripts": ["socket.js","eventPage.js"],
"persistent": true
}
},
"sockets":{
"udp": {"send":["*:*"], "bind":["*:*"]}
},
"permissions":["system.network","notifications"]
}
活动页面和套接字代码:
// eventPage.js
chrome.runtime.onStartup.addListener(function() {
console.log("I started up!");
socket.cleanup_create();
});
chrome.runtime.onSuspend.addListener(function() {
console.log("I am being suspended!");
});
// socket.js
function show(jsontext) {
var json_object = JSON.parse(jsontext);
console.log(json_object.TitleText);
console.log(json_object.MainText);
chrome.notifications.create("",
{type:'basic',iconUrl:'icon.png',title:json_object.TitleText,message:json_object.MainText},
function callback(){})
}
var socket = {
socketId:null,
/*==========Receive Callback=================*/
recieve_callback:function(rc){
console.log("Received on socket ID "+rc.socketId);
var dataView = new DataView(rc.data);
var decoder = new TextDecoder("utf-8");
var decodedString = decoder.decode(dataView);
console.log("Data Received and it is "+decodedString);
show(decodedString);
},
/*==========Receive Error Callback=================*/
recieve_error_callback:function(info){
console.log("Error on socket with code "+info.resultCode);
},
/*==========Bind Callback=================*/
bind_cb: function(s){
console.log("Socket seems to be binded result "+s);
chrome.sockets.udp.onReceive.addListener(socket.recieve_callback)
chrome.sockets.udp.onReceiveError.addListener(socket.recieve_error_callback)
},
/*==========Create Callback=================*/
create_cb: function(s){
console.log("Socket seems to be created id is "+s.socketId);
socket.socketId = s.socketId;
chrome.sockets.udp.bind(socket.socketId,"0.0.0.0",8080,socket.bind_cb);
},
/*==========Create Method=================*/
create: function(){
chrome.sockets.udp.create({persistent:true,name:"udp_socket",bufferSize:15000},socket.create_cb);
},
cleanup_create:function(){
chrome.sockets.udp.getSockets(function cleanup_create_cb(socketInfos){
console.log("Cleaning up existing sockets "+socketInfos.length);
for (i = 0; i < socketInfos.length; i++) {
chrome.sockets.udp.close(socketInfos[i],function socket_close_cb(){});
}
socket.create();
});
}
};
有什么方法可以让活动页面始终处于加载状态,或者有什么其他方法可以确保我始终获得 onReceive
活动吗?
Chrome 活动页面如何运作?这里是 the documentation,但简而言之:
- 执行您页面的顶级上下文,为事件注册侦听器。
- Chrome 构建一个应该唤醒页面的事件列表。
- 页面卸载:请注意,它完全破坏了 JS 上下文,包括侦听器 和任何已初始化的对象(例如您的
socket
对象)。 - 事件发生。 Chrome 查找是否需要唤醒您的页面。假设是这样。
- 页面再次加载,侦听器再次注册,然后Chrome调用它们。
引用文档:
Because the listeners themselves only exist in the context of the event page, you must use
addListener
each time the event page loads; only doing so atruntime.onInstalled
by itself is insufficient.
现在让我们看看这一行:
// Called in a callback to chrome.sockets.udp.bind()
bind_cb: function(s){
/* ... */
chrome.sockets.udp.onReceive.addListener(socket.recieve_callback)
/* ... */
}
再次加载页面时,这不会同步执行。因此,在第 5 步,Chrome 找不到合适的侦听器,因此未被调用。
请注意事件是全局的,即它没有绑定到套接字对象(卸载后不存在)。因此,您可以(并且应该)安全地将它绑定到一个分析回调参数的函数,以了解它在哪个套接字上运行。
因此,要使您的代码正常工作,addListener
必须 在事件页面加载时同步调用。