Как получить ценности из обещаний?

Я очень долго ломал голову над этой проблемой; слишком долго для чего это, почти наверняка тривиально.

Я хочу получить конкретное значение, как если бы оно было возвращено функцией. Обещания должны быть заполнителями для значений, а 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']
);
Другие вопросы по тегам