eleventy icon indicating copy to clipboard operation
eleventy copied to clipboard

Asynchronous filter returns a Promise object

Open ed-ponce opened this issue 1 year ago • 4 comments

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.

ed-ponce avatar Dec 22 '23 19:12 ed-ponce

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.

Snapstromegon avatar Dec 30 '23 13:12 Snapstromegon

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

ed-ponce avatar Dec 30 '23 21:12 ed-ponce

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.

Snapstromegon avatar Dec 31 '23 09:12 Snapstromegon

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.

ed-ponce avatar Dec 31 '23 18:12 ed-ponce