Chrome.runtime.onMessage ответ с асинхронным ожиданием
Я хочу использовать async ждут в прослушивателе onMessage:
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) =>{
var key = await getKey();
sendResponse(key);
});
Однако я получаю undefined, когда я отправляю сообщение.
Из документации для chrome.runtime.onMessage.addListener:
Эта функция становится недействительной, когда приемник событий возвращается, если только вы возвращаете true из прослушивателя событий, чтобы указать, что вы хотите отправить ответ асинхронно (это приведет к тому, что канал сообщения будет открыт для другой конец до вызова sendResponse).
Это работает, когда я использую обратный вызов.
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) =>{
getKey(key => {
sendResponse(key);
});
return true;
});
Однако я бы хотел использовать синтаксис ожидания. Но он не работает и все еще возвращает undefined:
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) =>{
var key = await getKey();
sendResponse(key);
return true;
});
Ответы
Ответ 1
Я обойти, извлекая в асинхронную функцию.
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
doSomethingWith(request).then(sendResponse);
return true; // return true to indicate you wish to send a response asynchronously
});
async function doSomethingWith(request) {
var key = await getKey();
// await .....
return key;
}
Возвращаемое значение async
функции неявно Promise.resolve
в Promise.resolve
. Смотрите асинхронный док.
Смотрите на сообщение.
Ответ 2
Не уверен, что среда выполнения расширений Chrome поддерживает синтаксис async/await, но вы можете использовать транспортер (например, Babel) для его преобразования, например, в ES5. Затем вы можете определить функцию-оболочку следующим образом:
function asChromeListener(listener) {
return (message, sender, sendResponse) => {
const returnValue = listener(message, sender);
if (isPromise(returnValue)) {
returnValue.then(sendResponse);
return true;
}
else {
if (typeof returnValue !== 'undefined') {
sendResponse(returnValue);
}
return false;
}
};
}
function isPromise(value) {
return typeof value === 'object' && value !== null && 'then' in value && 'catch' in value;
}
Что вы можете использовать как:
chrome.runtime.onMessage.addListener(asChromeListener(async (message, sender) => {
return await doMyAsyncWork(message);
});
Так как мы используем TypeScript, здесь также фрагмент, который мы фактически используем (с общими типами).
export function asChromeListener<M, S, R extends Function>(listener: (message: M, sender: S) => any) {
return (message: M, sender: S, sendResponse: R) => {
const returnValue = listener(message, sender);
if (isPromise(returnValue)) {
returnValue.then(sendResponse);
return true;
}
else {
if (typeof returnValue !== 'undefined') {
sendResponse(returnValue);
}
return false;
}
};
}
function isPromise(value: any) {
return typeof value === 'object' && value !== null && 'then' in value && 'catch' in value;
}
Ответ 3
Честно говоря, похоже, что расширения Google Chrome не поддерживают ключевое слово await
. Я успешно использовал асинхронный chrome.runtime.onMessage.addListener
раньше, и каждый раз, когда я пытаюсь использовать await
, я вижу эту синтаксическую ошибку в средствах отладки Chrome, в строке, которую я использую await
:
![ждать не поддерживается]()
Вот как я тестировал:
Я создал очень простой слушатель:
chrome.runtime.onMessage.addListener(function(data, MessageSender, sendResponse) {
sendResponse(awaitTester);
var async = true;
// returns true if asyncronous is needed
if (async) return true;
});
Моя функция awaitTester
выглядит следующим образом:
function awaitTester() {
var prom = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('test');
}, 4000);
});
var awaited = await prom;
return awaited;
}
наконец, мой отправитель сообщения - это то, что вы ожидаете:
chrome.runtime.sendMessage({}, function(message) {
debugger;
console.log(message);
});
И в отладчике/консоли я всегда получаю undefined
.