【问题标题】:Cannot resolve Promise in Node.js App with chrome-cookies-secure module无法使用 chrome-cookies-secure 模块解析 Node.js 应用程序中的 Promise
【发布时间】:2020-12-13 19:36:54
【问题描述】:

我正在开发一个需要访问 Google Chrome cookie 的本地 Node.js 应用程序。我发现 chrome-cookies-secure 库似乎可以完成这项工作,但我就是不知道下面的代码有什么问题。

const chrome = require('chrome-cookies-secure');

const domains = [
    "google.com"
];

const resolveCookies = async () => {
    let result = [];
    for(domain of domains) {
        await chrome.getCookies(`https://${domain}/`,  (err, cookies) => { 
            result.push(cookies); 
            // console.log(cookies); //? This is going to correctly print the results
        })
    }
    return result;
}

const final = resolveCookies();
console.log(final); //! This is going to return a Promise { <pending> } object

我的想法是我只想将来自所有域的 cookie 存储在一个列表中,但无论如何我都无法解决 Promise。 我没有看到任何有关此模块的异步调用的示例,但如果我不使用它,它将在脚本执行后返回一个空列表。

我的节点版本:v14.4.0

我做错了什么?

【问题讨论】:

  • resolveCookies 返回数组的 promise - async 函数 always 返回一个promise。试试resolveCookies.then((final) =&gt; console.log(final))
  • @jonrsharpe 感谢您的建议,但我回复了TypeError: resolveCookies.then is not a function
  • 对不起,错字;您需要调用函数resolveCookies().then(...
  • chrome.getCookies 是否真的返回了一个承诺?如果没有,awaiting 它根本没有帮助。
  • 瞥了一眼the source code 我不认为确实正确同步。 getCookiesasync,但它不会等待它对 getDerivedKey 的调用,反正它不是 async。尝试使用Util.promisify

标签: javascript node.js asynchronous cookies promise


【解决方案1】:

看起来getCookies 的实现没有正确地等待异步进程。您可以在the implementation 中看到,虽然getCookies 本身是async,但它会在不等待的情况下调用getDerivedKey(并且该函数无论如何都不是async)。

我建议不要尝试依赖此实现,而是使用Util.promisify 通过回调创建适当的承诺:

const util = require('util');

const chrome = require('chrome-cookies-secure');

const getCookies = util.promisify(chrome.getCookies);

// ...

const cookies = await getCookies(`https://${domain}/`);

注意,正如Reece Daniels 在cmets 中指出的那样,getCookies 实现实际上在回调之后 接受了profile 参数;如果需要使用该参数,则不能使用内置的promisify。你必须自己包装它,这可能看起来像例如:

const getCookies = (url, format, profile) => new Promise((resolve, reject) => {
    chrome.getCookies(url, format, (err, cookies) => {
        if (err) {
            reject(err);
        } else {
            resolve(cookies);
        }
    }, profile);
});

他们already tried to fix the promise upstream,但是PR已经快九个月没有合并了。


请注意,一旦你有一个工作函数可以调用,你也可以转换:

const resolveCookies = async () => {
    let result = [];
    for(domain of domains) {
        await chrome.getCookies(`https://${domain}/`,  (err, cookies) => { 
            result.push(cookies); 
            // console.log(cookies); //? This is going to correctly print the results
        })
    }
    return result;
}

简单地说:

const resolveCookies = () => Promise.all(domains.map((domain) => getCookies(`https://${domain}/`)));

【讨论】:

  • 非常感谢您的支持,因为我知道这是属于模块实现本身的东西。直到现在还没有看到关于这个的 PR :)
  • @Void 没问题,库实现(有一个async 函数实际上并没有在正确的时间解析)非常令人困惑!但请注意stackoverflow.com/help/someone-answers
  • 很好的@jonrsharpe,我刚刚阅读了您所链接的Util.promisify,我相信这将适用于所有情况,除非通过profile,因为profile 成为最后一个参数函数调用:nodejs.org/api/util.html#util_util_promisify_original -> Takes a function following the common error-first callback style, i.e. taking an (err, value) =&gt; ... callback as the last argument, and returns a version that returns promises. 只是一个观察,因为我认为这个答案解决了 OPs Q.. 看起来我的 PR 不太可能很快被合并到那个 repo。
  • @ReeceDaniels 好点;我会编辑,谢谢。不,我不会抱太大希望...
【解决方案2】:

async 函数返回Promise。 所以你的resolveCookies 函数也会返回一个Promise 你注意到的。

您需要将console.log.then 链接起来,例如

resolveCookies().then(console.log);

或者,如果您需要将其设置为final 之类的变量,您也需要等待Promise。在这种情况下,您需要async IIFE:

(async () => {
    const final = await resolveCookies();
    console.log(final);
})();

【讨论】:

  • 根据 cmets,它没有那么简单。
【解决方案3】:

试试这个。

const chrome = require('chrome-cookies-secure');

const domains = [
    "www.google.com"
];

const resolveCookies = async() => {
    let result = [];
    for (domain of domains) {
      const cookies = await getCookies(domain)
      result.push(cookies)
    }
    return Promise.resolve(result);
}

const getCookies = async (domain) => {
    chrome.getCookies(`https://${domain}/`,  (err, cookies) => { 
        return Promise.resolve(cookies);
    })
}

resolveCookies().then((resp) => {
    console.log('FINAL ',resp)
}).catch((e) => {
    console.log('ERROR ', e)
})

【讨论】:

  • 从回调中返回Promise.resolve不会使您的getCookies 实现返回cookie 的承诺。您甚至都不尝试处理err
  • 仅仅使用async 也无济于事。我已经在我的答案中举了一个如何手动执行此操作的示例。
猜你喜欢
  • 2017-05-22
  • 2017-04-20
  • 2021-05-21
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-30
相关资源
最近更新 更多