chrome.tabs.sendMessage
Подскажите пожалуйста, как мне отправить сообщение из 2го в 1й скрипт?
Смотрел вот тут описание, но без примера я ничего не понимаю... Есть 2 скрипта, 1й(background.js) висит в приложении постоянно, 2й(maps.js) подключается только к определённым страницам. В background.js
chrome.runtime.onMessage.addListener // Отлов сообщений
(
function(request, sender, sendResponse)
{
switch(request.id) // Это типа идентификатор сообщений
{
case 2: // GET запрос
{
GetHttpRequest(request.href, {rid: request.rid})
break
}
}
}
)
Это дополнительная информация из background.js
function GetHttpRequest(href, arg) // Запрос
{
var xhr = new XMLHttpRequest()
xhr.withCredentials = true
xhr.onreadystatechange = function(e)
{
e.data = arg
ProcessRequestChange.apply(this, arguments)
}
xhr.open('GET', href, true)
xhr.send(null)
}
function ProcessRequestChange(e) // Обработчик запроса
{
var xhr = this
if(xhr.readyState != 4) return
if(xhr.status == 200)
{
var html = xhr.responseText
switch(e.data.rid) // Это типа идентификатор запроса
{
case 3: // Покопаться в ответе на 'http://www.site.ru/bla-bla.php'
{
// Некий код который записывает необходимую информацию в str убрал для экономии
var str = 'ответ' // Пусть будет это ответом
chrome.tabs.query // Вроде это какое - то событие открытия(или получения) вкладок?
(
{active: true, currentWindow: true}, // Х.з
function(tabs)
{
chrome.tabs.sendMessage // Это то, что отправляет ответное сообщение
(
tabs[0].id, // Х.з, наверное идентификатор вкладки, куда отправить?
{greeting: "hello"}, // Это я так понял и есть ответ?
function(response) // А это вообще не нужно вроде...
{
console.log(response.farewell);
}
)
}
)
break
}
}
}
}
В maps.js:
chrome.runtime.sendMessage // Отправить сообщение в background.js
(
{id: 2, href: 'http://www.site.ru/bla-bla.php', rid: 3}, // Сделать запрос на адрес
function(response) // Функция ответа не может быть вызвана, т.к. ответ не отправляется из background.js
{
document.querySelector('#fades').style.display = 'inline'
document.querySelector('#guild').style.display = 'inline'
document.querySelector('#mercenary').innerHTML = 'jhg'
}
)
Так вот, вся проблема заключается в том, что в background.js сначала нужно послать запрос, получить ответ, покопаться в ответе, и только потом отправить ответ на сообщение в maps.js. |
*!*
- GetHttpRequest(request.href, {rid: request.rid})
*/!*
+ GetHttpRequest(request.href, {rid: request.rid, response: sendResponse});
*!*
- chrome.tabs.query // Вроде это какое - то событие открытия(или получения) вкладок?
(
{active: true, currentWindow: true}, // Х.з
function(tabs)
{
chrome.tabs.sendMessage // Это то, что отправляет ответное сообщение
(
tabs[0].id, // Х.з, наверное идентификатор вкладки, куда отправить?
{greeting: "hello"}, // Это я так понял и есть ответ?
function(response) // А это вообще не нужно вроде...
{
console.log(response.farewell);
}
)
}
)
*/!*
+ e.data.response(str);
|
Не получается получить текст ответа.
Сделал так, только передал строку с идентификатором: В background.js в обработчике запроса:
e.data.response({value: str})
В maps.js:
chrome.runtime.sendMessage
(
{id: 6, href: 'http://www.site.ru/bla-bla.php', rid: 3},
function(response)
{
alert('ответ пришел\n' + response.value)
}
)
Что - то ругается: Цитата:
|
chrome.runtime.onMessage.addListener // Отлов сообщений
(
function(request, sender, sendResponse)
{
switch(request.id) // Это типа идентификатор сообщений
{
case 2: // GET запрос
{
GetHttpRequest(request.href, {rid: request.rid, response: sendResponse})
break
}
}
*!*return true;*/!*
}
)
Цитата:
|
Спасибо ))
Всё работает. |
Блин, только что всё работало, и вдруг стало выдавать ошибку в background.js (e.data.response({value: str})):
Цитата:
background.js:
function GetHttpRequest(href, arg)
{
var xhr = new XMLHttpRequest()
xhr.withCredentials = true
xhr.onreadystatechange = function(e)
{
e.data = arg
ProcessRequestChange.apply(this, arguments)
}
xhr.open('GET', href, true)
xhr.send(null)
}
function ProcessRequestChange(e)
{
var xhr = this
if(xhr.readyState != 4) return
if(xhr.status == 200)
{
var html = xhr.responseText
switch(e.data.rid)
{
/*-------*/
case 3: // Гильдия наёмников
{
if(html.indexOf('возвращайся с победой') > -1 || (html.indexOf('у нас нет сейчас заданий') > -1 && html.indexOf('Вы получаете') < 0)) break
var s = html.indexOf('align=left rowspan=2>') + 21
var e = html.indexOf('</td>', s)
var str = html.substring(s, e)
e.data.response({value: str})
break
}
/*-------*/
case 0: break // Без обработки
}
}
}
chrome.runtime.onMessage.addListener
(
function(request, sender, sendResponse)
{
switch(request.id)
{
/*-------*/
case 6: // Гн
{
GetHttpRequest(request.href, {rid: request.rid, response: sendResponse})
return true
break
}
/*-------*/
}
return false
}
)
maps.js:
chrome.runtime.sendMessage
(
{id: 6, href: 'http://www.site.ru/bla-bla.php', rid: 3},
function(response)
{
//alert('ответ пришел\n' + response.value)
document.querySelector('#fades').style.display = 'inline'
document.querySelector('#guild').style.display = 'inline'
document.querySelector('#mercenary').innerHTML = response.value
}
)
|
А вот так всё работает:
//var s = html.indexOf('align=left rowspan=2>') + 21
//var e = html.indexOf('</td>', s)
var str = 'errfsdf'//html.substring(s, e)
|
Вот эта строчка:
var e = html.indexOf('</td>', s)
тут вы переназначаете переменную "e", соответственно "e.data" уже ничего не содержит.) |
От блин, невнимательность, спасибо ))
|
Вложений: 1
Блин, задолбала уже эта ошибка:
Цитата:
Просто я сделал одну фигню всплывающим окном(вставил часть другой страницы), через localStorage убрал лишние запросы на сайт... Вложение 3343 Вот это всё равно вызывается:
chrome.runtime.sendMessage
(
{id: 6, href: 'http://www.site.ru/bla-bla.php', rid: 3},
function(response)
{
alert('ответ')
document.querySelector('#fades').style.display = 'inline'
document.querySelector('#guild').style.display = 'inline'
document.querySelector('#mercenary').innerHTML = response.value
}
)
А это обработчик(ну или прослушиватель, как его там правильно) этого сообщения. Тут всё нормально с return'ами break'ами? Просто я не привык к этой дикости в свитче...
chrome.runtime.onMessage.addListener
(
function(request, sender, sendResponse)
{
switch(request.id)
{
case 4: // Получить значение localStorage
{
var sid = request.sid
sendResponse({sid: sid, value: localStorage[sid]})
break
}
case 6: // Обработчик
{
var l = localStorage['mercenary_guild']
if(l != undefined && l > parseInt(+ new Date() / 1000)) break
alert('запрос')
GetHttpRequest(request.href, {rid: request.rid, response: sendResponse})
return true
break
}
}
return false
}
)
Когда срабатывает это условие: if(l != undefined && l > parseInt(+ new Date() / 1000)) break Появляется ошибка. Я понял, что нет параметра value в ответе(он вообще пустой). Не понятно какого хрена он вообще приходит, ведь там нет sendResponse()... Если всё так и должно работать, можно хотя бы как - то проверить, что ответ пустой? |
Цитата:
проверить на тип undefined лучше typeof L === "undefined"или !!(L) еще лучше проверять на конкретный тип typeof L === "number" второе условие вообще безобразно - чем вам так объект Date не понравился, что вы его на 1000 делите? )) если по-вашему, то if ( !(typeof === "undefined") && L > Math.round(Date.now()/1000) ) |
Цитата:
не назначайте ее, если не надо или function(){} укажите |
Цитата:
maps.js каким образом подключается к страницам? |
Цитата:
Цитата:
|
это eventPage.js (по-вашему background)
list = ['google.ru','mail.ru','yandex.ru'];
//chrome.webNavigation.onDOMContentLoaded.addListener(onNavigate);
chrome.webNavigation.onCompleted.addListener(onNavigate);
function onNavigate(details){
var len = list.length;
var tabID = details.id;
var tabUrl = details.url.replace(/^https?\:\/\/(www\.)?/, '');
for (var i=0; i < len; i++){
if( tabUrl.startsWith(list[i]) ){
if (details.frameId != 0) break; /*иначе, например, bing "съедает" две загрузки, те msg будет показан 2*/
var siteName = list[i];
var msg = list[i];
chrome.tabs.insertCSS(tabID, {file:"css/content_style.css"});
chrome.tabs.executeScript(tabID, {file: "js/content_script.js"});
tabConnect({msg_:msg, name_:siteName});
};
};
function tabConnect(msg) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var port = chrome.tabs.connect(tabs[0].id);
port.postMessage(msg);
port.onMessage.addListener(function getResp(response){
if(response.close_){
sessionStorage.setItem(response.name_, 3);
};
});
});
};
а это в том самом скрипте, который вживляется в указанные в массиве сайты нексолькими строками выше, так называемый content_script.js
var siteName;
var portName;
var div = document.createElement('div');
chrome.runtime.onConnect.addListener(function(port) {
portName = port;
port.onMessage.addListener(function(msg) {
if(msg.msg_) showMessage(msg.msg_);
if(msg.name_) siteName = msg.name_;
});
});
function showMessage(msg){
div.className = "injection";
div.innerHTML = '<p class="inj_message">' + msg + '</p>';
div.addEventListener('click', clickHandler);
document.body.appendChild(div);
};
function clickHandler(){
document.body.removeChild(div);
portName.postMessage({name_:siteName, close_:true});
};
я, конечно, свой код покрамсал и поэтому могут быть ошибки, но суть такова: сообщение - ответ. если надо длительное общение поддерживать, то лучше создавать именованный канал и не забывать его закрывать, а то скрипты так и будут висеть. |
Цитата:
Цитата:
Math.round(Date.now()/1000) Я уже поменял, просто писал это до того как посмотрел другую тему. Цитата:
Вешается на "невидимую" вкладку. Он нужен, т.к. приложение - бот для онлайн игры. Он работает даже когда нет открытых вкладок с самой игрой. maps.js подключается в манифесте через указанный адрес. Цитата:
Просто мало того, что там всё по английски(гугл перевод конченный), так ещё терминами непонятными сыпят. Ничего не понятно, я не могу ничего там найти, из того, что мне нужно... Спасибо, понял теперь в чём дело. )) Цитата:
Ну и в принципе мне обычного хватит вполне. Т.к. страницы открываются/закрываются... Суть вот в чём, открываю страницу сайта("карта", к ней и подгружается maps.js), получаю 3 ячейки из фонового скрипта(background.js) с настройками. Далее несколько проверок(есть ли задания гильдии наёмников, они либо висят доступные либо сданы и нужно подождать минут 20 до следующего) - запрос на другую страницу(самой гильдии, там пишут доступно или нет и сколько ждать), проверка, вывод посередине страницы части страницы из запроса. Вот я сейчас на этапе "оптимизации" этого не единственного функционала приложения. На странице карты можно узнать взято или нет задание, а остальное только запросом. Чтобы не делать каждый раз запрос(при обновлении карты, а она постоянно в работе), я создал ячейку в памяти и храню в ней время когда будет доступно задание(1й запрос всё - таки делается, чтобы узнать это время). Ну и вот, только на клиентской стороне всё считается... |
Во, всё заработало:
chrome.runtime.onMessage.addListener
(
function(request, sender, sendResponse)
{
switch(request.id)
{
case 4: // Получить значение localStorage
{
var sid = request.sid
sendResponse({sid: sid, value: localStorage[sid]})
return false
break
}
case 6: // Гн
{
var l = localStorage['mercenary_guild']
if(l != undefined && l > Math.round(Date.now() / 1000)) break
alert('запрос')
GetHttpRequest(request.href, {rid: request.rid, response: sendResponse})
break
}
}
return true
}
)
|
А если нужно несколько раз вернуть ответ(асинхронно), то никак не получится?
Т.е. я 1 раз посылаю сообщение в другой скрипт, а тот что - то там делает, и отправляет ответы, при необходимости... Цитата:
Долгоживущее соединение не поможет? |
Артист, таким образом - да.
Для более сложного "постоянного" общения есть connect. |
Спасибо )
|
Вроде понял, нашел где по русски объясняют...
Так нужно отправлять сообщения из background.js в maps.js
chrome.tabs.query // Запрос браузеру на получение id всех вкладок
(
{url: "http://www.site.ru/*"}, // Параметры(фильтры)
function(tabs) // Функция вызывающаяся после получения
{
var l
if((l = tabs.length) != 0) return // Если нет подходящих вкладок
var i = -1
while(++i < l) chrome.tabs.sendMessage(tabs[l].id, {greeting: "hello"}) // Отправка сообщения вкладкам
}
)
В maps.js должна быть функция chrome.runtime.onMessage.addListener. Я хочу сделать на какой вкладке был запрос, туда и слать ответные сообщения. Т.е. я из maps.js отправляю один запрос в background.js, и уже в этом запросе передаю нужный ид вкладки. В background.js уже будет отослано этой вкладке несколько "ответов". Как получить id текущей вкладки? |
Нашел:
chrome.tabs.getSelected
(
null,
function(tab)
{
console.log(tab)
}
)
Оказалось, что из контент скрипта нет доступа к апи хрома. Уродство. |
| Часовой пояс GMT +3, время: 04:47. |