Как получить ценности из обещаний?
Я очень долго ломал голову над этой проблемой; слишком долго для чего это, почти наверняка тривиально.
Я хочу получить конкретное значение, как если бы оно было возвращено функцией. Обещания должны быть заполнителями для значений, а onAuthRequired принимает функцию, которая возвращает блокирующий объект ответа:
{
authCredentials: {
username: "..."
password: "..."
}
}
Поэтому мне нужно создать функцию, которая возвращает эту структуру и делает это асинхронно. Поэтому я положил в async
ключевое слово, то есть я могу await
разрешение обещания... я думаю. Но прежде чем я смогу построить эту структуру, я должен выполнить асинхронную операцию с API-интерфейсом nativeMessaging... который не возвращает обещание... Я думаю. Так что я должен как-то обернуть это в обещание...
Изменить: я обновил код ниже, чтобы отразить текущее состояние, объединение всех великих ответов до сих пор.
async function get_data() {
return new Promise((resolve, reject) => {
var data = chrome.runtime.sendNativeMessage('Host', {text:'Ready'},
function(response) {
resolve(response);
}
};
})
};
async function get_creds() {
var data = await get_data();
if (null != data) {
creds = JSON.parse(data);
return {
authCredentials: {
username: creds.username,
password: creds.password
}
};
}
};
chrome.webRequest.onAuthRequired.addListener(
function(details, get_creds),
{urls: ["<all_urls>"]},
['blocking']
);
Я экспериментировал со следующим кодом:
chrome.webRequest.onAuthRequired.addListener(
function handler(details){
var creds = await get_data(); // Uncaught SyntaxError: unexpected identifier
creds = JSON.parse(creds);
return {
authCredentials: {
username: creds.username,
password: creds.password
}
};
},
{urls:["<all_urls>"]},
['asyncBlocking']
);
Это называется get_data()
напрямую, но с неожиданной ошибкой идентификатора.
Если бы я удалил await
Ключевое слово это "работало"... то есть оно пыталось что-то сделать с событием... но не передавало объект обратно. Что он сделал, это установил сообщение в левом нижнем углу экрана "ожидание на добавочный номер..." и вызов get_data()
функционировать около 3 раз.
Если я изменю ['asyncBlocking']
в ['blocking']
, он не может вызвать get_data() вообще.
Я понятия не имею, что здесь происходит.
Так что это должно передать значение, возвращаемое Native Messaging Host обратно через эти странные обещания, а затем подключиться прямо туда, где onAuthRequired ожидает, что его структура JSON будет возвращена...
Редактировать: Я ожидаю, что объект, возвращенный get_creds(), будет передан onAuthRequired. На данный момент есть токен "неожиданный токен" на function(details, get_creds)
... так что это явно не так. Я подозреваю, что мне может понадобиться другое обещание в get_creds()
который заменит для authCredentials
объект...
Помимо всех неожиданных идентификаторов, происхождение которых я не могу понять, у меня есть ощущение, что я делаю все это задом наперед.
Добро пожаловать в конец моего ума... и спасибо за любой свет, который вы можете пролить на мое невежество.
4 ответа
Чтобы ответить на вопрос "Как я могу получить ценности из обещаний?" Мне сообщили все 3 предоставленных примера. Однако ни у кого не было полного решения.
Редактировать:
Полное решение моей конкретной проблемы (как это происходит, он использовал обратные вызовы, а не обещания) здесь.
Предостережение - хотя мне удалось вернуть объект обратно onAuthRequest
при передаче значений обратно через обещания возникает некоторая проблема с объектом, так как он не дает желаемого эффекта.
Во-первых, get_data()
нужно было изменить.
async function get_data() {
return new Promise((resolve, reject) => {
const data = chrome.runtime.sendNativeMessage(
'host',
{text: "Ready"},
function(response){
resolve(response);
}
);
});
});
Затем я возвращал обещание get_creds()
(сейчас get_data()
)... но я ничего с этим не делал. Мне нужно было использовать promiseFunction.then(function(response){ ... })
для того, чтобы переместить разрешенную стоимость обещания. Это тоже было полезно.
chrome.webRequest.onAuthRequired.addListener(
function handler(details){
get_data().then(function(response) {
// --> result's value is available in here
return {
authCredentials: {
username: response.username,
password: response.password
}
};
});
},
{urls: ["<all_urls>"]},
['asyncBlocking'] // --> not just 'Blocking'
);
Кроме того, мне нужно было вернуть объект - что делается с помощью обратного вызова:
chrome.webRequest.onAuthRequired.addListener(
function handler(details){ // --> callback
...
return { // --> an object
authCredentials: {
username: response.username,
password: response.password
}
...
},
{urls: ["<all_urls>"]},
['asyncBlocking'] // --> not just 'Blocking'
);
Наконец, должна быть изменена функция обратного вызова, позволяющая обещать что-то в promise.then()... Найдено здесь
chrome.webRequest.onAuthRequired.addListener(
function handler(details){
get_data().then(function(response) {
... )
будет выглядеть так:
chrome.webRequest.onAuthRequired.addListener(
function handler(details){
return get_data().then(function(response) {
... )
Так вот, как вывести значение из этого обещания в функцию обратного вызова... Однако у меня есть еще много работы, чтобы получить желаемый результат.
Вы возвращаете обещание на get_creds(), но ничего не делаете с ним.
попробуйте вернуть только тот результат, который вы хотите на get_creds()
как это:
async function get_creds() {
var data = await get_data();
if (null != data) {
var creds = JSON.parse(data)
return {
authCredentials: {
username: creds.username,
password: creds.password
}
};
} else {
throw new Error('QuitMyJob');
}
}
}
chrome.webRequest.onAuthRequired.addListener(
get_creds(), //should resolve with the value I want to use?
{urls: ["<all_urls>"]},
['blocking']
);
Ваш get_data()
метод должен измениться.
sendNativeMessage
возвращает обещание, если я прав. Фирефокса sendNativeMessage
это возвращает обещание.
Вы должны решить обещание, используя .then
а затем разрешить его с помощью обертки resolve
Перезвоните.
async function get_data() {
return new Promise((resolve, reject) => {
var dataPromise = chrome.runtime.sendNativeMessage('Host', {text:'Ready'});
dataPromise.then(response => {
resolve(response);
}).catch(err => {
reject(err);
})
}
});
Если функция не возвращает обещание, то похоже, что она принимает и необязательный обратный вызов, который будет иметь ответ.
https://developer.chrome.com/apps/runtime
async function get_data() {
return new Promise((resolve, reject) => {
var dataPromise = chrome.runtime.sendNativeMessage('Host', {text:'Ready'}, function(response) {
resolve(response);
});
}
});
Кроме того, addListener ожидает обратного вызова, но вы, кажется, вызываете его. И документация не показывает никаких других аргументов. Вы можете проверить это https://developer.chrome.com/extensions/webRequest
chrome.webRequest.onAuthRequired.addListener(
get_creds, //should resolve with the value I want to use?
{urls: ["<all_urls>"]},
['blocking']
);
Если ваша функция должна возвращать объект, а не обещание (что async
функция всегда возвращает), тогда простая функция сделает:
function getData() {
const data = chrome.runtime.sendNativeMessage('Host', {text:'Ready'});
if (data) {
const creds = JSON.parse(data);
return {
authCredentials = {
username: creds.username,
password: creds.password
}
};
} else {
// handle the error somehow
}
};
chrome.webRequest.onAuthRequired.addListener(
getData
{urls: ["<all_urls>"]},
['blocking']
);