Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asynchronous filter returns a Promise object #3133

Open
patrulea opened this issue Dec 22, 2023 · 4 comments · May be fixed by #3141
Open

Asynchronous filter returns a Promise object #3133

patrulea opened this issue Dec 22, 2023 · 4 comments · May be fixed by #3141
Labels
needs-reproduction Having trouble reproducing! Can anyone confirm? needs-triage

Comments

@patrulea
Copy link

patrulea commented Dec 22, 2023

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.

@Snapstromegon
Copy link
Member

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 Snapstromegon added the needs-reproduction Having trouble reproducing! Can anyone confirm? label Dec 30, 2023
@patrulea
Copy link
Author

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

@Snapstromegon
Copy link
Member

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.

@patrulea
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-reproduction Having trouble reproducing! Can anyone confirm? needs-triage
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants