【问题标题】:How to get values out of promises?如何从承诺中获取价值?
【发布时间】:2018-05-16 06:29:07
【问题描述】:

我很长时间以来一直在努力解决这个问题;对于它来说太长了,几乎可以肯定是微不足道的。

我想得到一个特定的值,就好像它是一个函数返回的一样。 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 关键字,它“工作”......也就是说,它试图对事件做一些事情......但它没有将对象传回。它所做的是在屏幕左下角设置一条消息“等待扩展......”并调用get_data()函数大约3次。

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

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


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

编辑: 我希望 get_creds() 返回的对象被传递给 onAuthRequired。 目前,function(details, get_creds) 上有一个“意外令牌”令牌......所以这显然是错误的。 我怀疑我可能需要在 get_creds() 中使用另一个承诺来填充 authCredentials 对象...

除了所有我无法理解其来源的意外标识符之外,我有一种感觉,我在做这整件事。

欢迎结束我的智慧......感谢您对我的无知的任何启发。

【问题讨论】:

  • 你能分享一下输出是什么吗?预期的输出是什么?
  • 没有输出 - 代码没有运行并且没有输出。预期的结果在帖子的顶部 - 显示的 JSON 是应该生成的。

标签: javascript asynchronous google-chrome-extension promise


【解决方案1】:

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

编辑:

我的具体问题的完整解决方案(碰巧,它使用回调,而不是承诺)是here


警告 - 虽然我已经设法通过 promise 将值传递回 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) {
... )

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我确实注意到这个 API 上 Chrome 和 Firefox 之间的差异 - 即,正如您敏锐地指出的那样,缺乏承诺。我认为您给出的第二个答案更接近事实-无论如何我都会尝试。
    • 是的,你可以试试,我猜两者都可以。告诉我进展如何。
    • 我一直在使用您提供的第二个版本以及来自@marceloemanoel 的代码 - 此时看起来还不错,但由于onAuthRequired.addListener 的其他问题而没有被解雇它看起来像不过,第二个版本与 API 的 chrome 版本匹配 - 谢谢!编辑:正如预期的那样,它似乎在获取数据方面工作得很好。再次感谢您
    • 那么,直接调用不会返回 Promise 吗?该死的跨浏览器的这些细微差别。如果一切正常,请告诉我。
    • 仅供参考 - chrome.runtime.sendNativeMessage() 不返回承诺。它改为接受回调函数。请参阅文档 - developer.chrome.com/extensions/…
    【解决方案3】:

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

    【讨论】:

    • 感谢@BenRondeau 的帮助!既然chrome.runtime.sendNativeMessage()是异步的,那剩下的代码会不会在不保证及时得到响应的情况下运行?
    • 这取决于chrome.runtime.sendNativeMessage() 的写法。你试过这个解决方案了吗?
    • 我现在正在登录我的工作机器进行尝试 - 结果如下
    • 结果:我更改了// handle the error somehow 行以显示警告框。它不断地碰到错误块。至少,它似乎走了那么远——所以这是朝着正确方向迈出的一步
    • 它总是会遇到 else 条件,因为 Chrome API 甚至不返回 Promise。就算实现了也不会实现?
    【解决方案4】:

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

    【讨论】:

    • 你的函数正在使用await,但它没有使用async关键字
    • 感谢您的帮助,@marceloemanoel!使用您的代码,看起来我已经拥有的 get_data() 函数就足够了吗?看起来这里的 await 将确保我在尝试将某些内容传递给 onAuthRequired 之前得到来自本机消息传递的响应?
    • @marceloemanoel - 看起来我们已经非常接近了!使用您编写的代码,似乎一切都在进行中。我现在得到:Uncaught Error: invocation of form webRequestInternal.addEventListener( ... ) doesn't match definition webRequestInternal.addEventListener( function callback, object filter, optional array ... ) 我将 get_creds() 更改为:` function callback({ return get_creds(); //also without return });` 但这似乎没有让主机参与,并且没有任何内容传递到 onAuthRequired 侦听器。
    • @LexWoodfinger 检查我更新的答案。您只需要将 get_creds 作为参数发送到 addListener 作为参数。
    • @NanduKalidindi - 这看起来像是崩溃的地步......它又回到了第一格 - 我如何从承诺中获得价值给听众? chrome...addListener(callback, {urls...}, [...]);已经将回调作为参数,对吗?如果是这样的话; chrome...addListener(get_creds(), {urls...}, [...]);应该发送 get_creds 作为参数?或者,正如 Ben Rondeau 所写: chrome...addListener(get_creds, {urls...}, [...]);从 get_creds 中删除括号的位置?
    猜你喜欢
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 2022-12-17
    相关资源
    最近更新 更多