Reputation: 67
I'm working on a local Node.js app that needs to access the Google Chrome cookies. I've found the chrome-cookies-secure
library that seems to do the job but I just can't figure out what's wrong with the code below.
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
The idea is that I just want to store the cookies from all the domains in a list but no matter what I cannot resolve the Promise. I didn't see any examples with the async call for this module but if I don't use it it's going to return me an empty list after the script execution.
My Node Version: v14.4.0
What am I doing wrong?
Upvotes: 2
Views: 547
Reputation: 122090
It looks like the implementation of getCookies
is not correctly awaiting the asynchronous processes. You can see in the implementation that although getCookies
itself is async
, it calls getDerivedKey
without awaiting it (and that function isn't async
anyway).
Rather than trying to rely on this implementation, I'd suggest using Util.promisify
to create a proper promise via the callback:
const util = require('util');
const chrome = require('chrome-cookies-secure');
const getCookies = util.promisify(chrome.getCookies);
// ...
const cookies = await getCookies(`https://${domain}/`);
Note that, as Reece Daniels pointed out in the comments, the getCookies
implementation actually takes a profile
parameter after the callback; if you need to use that parameter, you can't use the built-in promisify
. You'd have to wrap it yourself instead, this could look like e.g.:
const getCookies = (url, format, profile) => new Promise((resolve, reject) => {
chrome.getCookies(url, format, (err, cookies) => {
if (err) {
reject(err);
} else {
resolve(cookies);
}
}, profile);
});
They already tried to fix the promise upstream, but the PR hasn't been merged in nearly nine months.
Note that once you have a working function to call you can also convert:
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;
}
to simply:
const resolveCookies = () => Promise.all(domains.map((domain) => getCookies(`https://${domain}/`)));
Upvotes: 3
Reputation: 69
try this.
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)
})
Upvotes: -1
Reputation: 317
An async
function returns a Promise
.
So your resolveCookies
function will also return a Promise
as you noticed.
You need to either chain the console.log
with a .then
e.g.
resolveCookies().then(console.log);
Or if you need to set it to a variable like final
you need to await that Promise
too. In that case you need an async
IIFE:
(async () => {
const final = await resolveCookies();
console.log(final);
})();
Upvotes: -1