Асинхронная отправка ответа в onMessage-прослушиватель [дубликат]

131
задан Xan 7 September 2014 в 19:16
поделиться

3 ответа

Из документация для chrome.runtime.onMessage.addListener :

Эта функция становится недействительной, когда приемник событий возвращается, если вы не вернете true из прослушивателя событий, чтобы указать, что вы хотите для отправки ответа асинхронно (это приведет к тому, что канал сообщения будет открыт на другом конце, пока не будет вызван вызов sendResponse).

. Вам просто нужно добавить return true; после вызова getUrls, чтобы указать, что вы вызовите функцию ответа асинхронно.

293
ответ дан rsanchez 28 August 2018 в 07:45
поделиться

Принятый ответ правильный, я просто хотел добавить пример кода, который упростит это. Проблема в том, что API (на мой взгляд) не очень хорошо разработан, потому что он заставляет нас разработчиков знать, обрабатывается ли какое-либо конкретное сообщение async или нет. Если вы обрабатываете много разных сообщений, это становится невыполнимой задачей, потому что вы никогда не знаете, если в какой-то степени в какой-то функции переданный метод sendResponse будет вызываться как асинхронный или нет. Рассмотрим это:

chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {
if (request.method == "method1") {
    handleMethod1(sendResponse);
}

Как узнать, будет ли в самом низу handleMethod1 вызов асинхронным или нет? Как может кто-то, кто изменяет handleMethod1, знает, что он сломает вызывающего абонента, введя что-то async?

Мое решение таково:

chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) {

var responseStatus = { bCalled: false };

function sendResponse(obj) {  //dummy wrapper to deal with exceptions and detect async
    try {
        sendResponseParam(obj);
    } catch (e) {
        //error handling
    }
    responseStatus.bCalled= true;
}

if (request.method == "method1") {
    handleMethod1(sendResponse);
}
else if (request.method == "method2") {
    handleMethod2(sendResponse);
}
...

if (!responseStatus.bCalled) { //if its set, the call wasn't async, else it is.
    return true;
}

});

Это автоматически обрабатывает возвращаемое значение, независимо как вы решаете обработать сообщение. Обратите внимание, что это предполагает, что вы никогда не забудете вызвать функцию ответа. Также обратите внимание, что хром мог автоматизировать это для нас, я не понимаю, почему они этого не сделали.

7
ответ дан Roy Rico 28 August 2018 в 07:45
поделиться

Вы можете использовать мою библиотеку https://github.com/lawlietmester/webextension , чтобы сделать эту работу как в Chrome, так и в FF с помощью Firefox без обратных вызовов.

Ваш код будет выглядеть так:

Browser.runtime.onMessage.addListener( request => new Promise( resolve => {
    if( !request || typeof request !== 'object' || request.type !== "getUrls" ) return;

    $.ajax({
        'url': "http://localhost:3000/urls",
        'method': 'GET'
    }).then( urls => { resolve({ urls }); });
}) );
1
ответ дан Rustam 28 August 2018 в 07:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: