如何从承诺中获取价值?

时间:2017-12-02 06:54:53

标签: javascript asynchronous google-chrome-extension promise

我很长时间以来都在抨击这个问题。它太长了,几乎肯定是微不足道的。

我想得到一个特定的值,就好像它是由函数返回的一样。 Promise应该是值的占位符,onAuthRequired接受一个返回a blocking response object的函数:

{
  authCredentials: {
    username: "..."
    password: "..."
  }
}

所以我需要创建一个返回该结构的函数,并异步执行。所以我添加了async关键字,这意味着我可以await解决承诺......我想。 但在我构建该结构之前,我必须对nativeMessaging API执行异步操作...这不会返回一个承诺......我想。 因此,我必须以某种方式将其包装在承诺中......

编辑: 我已经更新了下面的代码,以反映当前的状态,这是迄今为止所有重要反应的混合。

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关键字,那么&#34;工作&#34; ......也就是说,它试图在事件上做点什么......但它并没有将对象传回去。它所做的是在屏幕的左下方设置一条消息&#34;等待扩展......&#34;并且调用get_data()函数大约3次。

如果我将['asyncBlocking']更改为['blocking'],则根本无法调用get_data()。

我不知道这里发生了什么。

所以这应该通过这些奇怪的承诺传递Native Messaging Host返回的值,然后直接插入到onAuthRequired期望返回JSON结构的地方......

编辑: 我希望get_creds()返回的对象传递给onAuthRequired。 在这一点上,有一个意想不到的令牌&#39; function(details, get_creds)上的令牌......这显然是错误的。 我怀疑我可能需要在get_creds()中使用另一个承诺来填充authCredentials对象......

除了我无法理解的所有意外标识符之外,我感觉我已经倒退了这一切。

欢迎来到我的智慧结束......并感谢你能为我的无知带来任何光明。

4 个答案:

答案 0 :(得分:1)

您正在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']
);

答案 1 :(得分:1)

您的get_data()方法需要更改。

如果我是正确的,

sendNativeMessage会返回一个承诺。 Firefox的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);
    })    
  }
});

如果函数没有返回一个promise,那么看起来它会接受并且可选的回调会有响应。

https://developer.chrome.com/apps/runtime#method-sendNativeMessage

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#event-onAuthRequired

chrome.webRequest.onAuthRequired.addListener(
  get_creds, //should resolve with the value I want to use?
  {urls: ["<all_urls>"]},
  ['blocking']
);

答案 2 :(得分:0)

如果你的函数需要返回一个对象而不是一个promise(这是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']
);

答案 3 :(得分:0)

回答问题“如何从承诺中获取价值?”我收到了所有3个提供的示例。然而,没有人有完整的解决方案。

编辑:

完全解决我的具体问题(因为它发生了,它使用了回调,而不是承诺)是here

警告 - 虽然我已经设法通过将值传递回promises而将对象传递回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){ ... })来移除promise的已解析值。 This也很有帮助。

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()输出一些东西...... 找到here

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) {
... )

这就是如何从该承诺中获取价值并进入回调函数......但是,我还有更多的工作要做,以获得所需的结果。