eleventy
eleventy copied to clipboard
Asynchronous filter returns a Promise object
Operating system
macOS Sonoma 14.2.1
Eleventy
2.0.1
Describe the bug
I’m writing an async filter to fetch the data of a Sanity document based on its ID.
Logging the data in the console works as expected, but trying to render the result within a template doesn’t, as it returns an empty object (Promise { <pending> }).
<code @text="sRef(reference)"></code>
module.exports = eleventyConfig => {
eleventyConfig.addJavaScriptFunction("sRef", async reference => {
try {
const response = await fetch(`https://${process.env.SANITY_STUDIO_PROJECT_ID}.api.sanity.io/v${process.env.SANITY_STUDIO_API_VERSION}/data/query/${process.env.SANITY_STUDIO_DATASET}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.SANITY_STUDIO_API_TOKEN}`
},
body: JSON.stringify({
query: `*[_id == $referenceId][0]`,
params: {
referenceId: reference
}
})
});
if (!response.ok) {
throw new Error(`Error fetching data: ${response.statusText}`);
}
const data = await response.json();
return data.result;
} catch (error) {
console.error(`Error fetching data from Sanity: ${error.message}`);
return null;
}
})
}
This is a WebC template but I don’t think it’s related to that.
Hey @patrulea, I tried reproducing your issue, but wasn't able too. I created a Gist here with my experiment: https://gist.github.com/Snapstromegon/1f643930a37d0383f414eb2bfc8492dc
As far as I can tell async filters should work correctly. In my test I just switched the sanity endpoint to swapi.dev. Maybe you could create a reproducable git repo or something, so I can test it with your code.
https://github.com/patrulea/issue-3133
There it is. Logging the data from the filter does result in what I’m expecting. Though, logging it from the template (through the Eleventy log() helper results in an empty Promise object (as described above).
Ahh, that's the issue.
Yes, the log filter currently doesn't await the promise before logging it.
A workaround for this in cases where you can't await the value before passing it into the log filter is, to use the .then method of the Promise like this:
<code @text="sRef('movie_10681').then(log)"></code>
In my opinion it would be nice to change the log filter to await the value by default. That way you could use the filter like you expected to above.
oooh right. I successfully rendered the fetched data with sRef('movie_10681').then(JSON.stringify). But how can I use it to access the keys? An <h2> with the title found in the fetched object, for example.