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

addNunjucksAsyncFilter not passing callback function #1913

Closed
cfjedimaster opened this issue Jul 29, 2021 · 6 comments
Closed

addNunjucksAsyncFilter not passing callback function #1913

cfjedimaster opened this issue Jul 29, 2021 · 6 comments

Comments

@cfjedimaster
Copy link

Describe the bug
I'm tryjng to test addNunjucksAsyncFilter and have noticed it fails because callback is not passsed to the function.

To Reproduce

I copied the example from here: https://www.11ty.dev/docs/languages/nunjucks/#asynchronous-nunjucks-filters

Here's my complete .eleventy.js:

const fetch = require('node-fetch');

module.exports = function(eleventyConfig) {

	eleventyConfig.addFilter("fetch", async function(url) {
		console.log('called fetch with '+url);
		let resp = await fetch(url);
		let data = await resp.json();
		console.log('data', data.results.length);
		return data;
  	});

	
	eleventyConfig.addNunjucksAsyncFilter("myAsyncFilter", function(value, callback) {
		setTimeout(function() {
		  callback(null, "My Result");
		}, 100);
	  });

}

Expected behavior
It will run as expected. :)

Environment:

  • OS and Version: WSL
  • Eleventy Version [via eleventy --version or npx @11ty/eleventy --version] 0.12.1
@pdehaan
Copy link
Contributor

pdehaan commented Jul 29, 2021

Works for me:

// .eleventy.js
const fetch = require("node-fetch");

module.exports = function (eleventyConfig) {
  eleventyConfig.addFilter("fetch", async function (url) {
    console.log(`called fetch with ${url}`);
    let resp = await fetch(url);
    let data = await resp.json();
    console.log("data", data.length);
    return data.slice(0, 3);
  });

  eleventyConfig.addNunjucksAsyncFilter(
    "resolve",
    async function (promise, callback) {
      try {
        callback(null, await promise);
      } catch (err) {
        callback(err);
      }
    }
  );

  eleventyConfig.addNunjucksAsyncFilter(
    "myAsyncFilter",
    function (value, callback) {
      setTimeout(function () {
        callback(null, `Hello, ${value}!`);
      }, 100);
    }
  );

  return {
    dir: {
      input: "src",
      output: "www",
    },
  };
};
---
# src/index.njk
---

<pre data-fetch>
{{ "https://haveibeenpwned.com/api/v3/breaches/" | fetch }}
</pre>

<pre data-fetch-resolve>
{{ "https://haveibeenpwned.com/api/v3/breaches/" | fetch | resolve }}
</pre>

<pre data-my-async-filter>
{{ "Peter" | myAsyncFilter }}
</pre>

OUTPUT

<pre data-fetch>
[object Promise]
</pre>

<pre data-fetch-resolve>
[object Object],[object Object],[object Object]
</pre>

<pre data-my-async-filter>
Hello, Peter!
</pre>

@cfjedimaster
Copy link
Author

Weird - did a new test and it does work. Going back to my code in a bit to see what I did wrong. Sorry for the mess, this was part of me testing other stuff too.

@cfjedimaster
Copy link
Author

Ahah, I'm seeing the issue a bit. When I do this:

{% set ships %}
{{ 'https://swapi.dev/api/starships' | myAsyncFilter }}
{% endset %}

I get the error. I thought the NJK set command would take the output from my function and store it in a variable. That should work, right?

@pdehaan
Copy link
Contributor

pdehaan commented Jul 30, 2021

I get the error. I thought the NJK set command would take the output from my function and store it in a variable. That should work, right?

Oh. No clue. You might have to see if you can build a nunjucks-specific test case and ask in that repo. I think I tried this and it worked, but I haven't tried with paired {% set %}..{% endset %} tags.

{%- set breaches = "https://haveibeenpwned.com/api/v3/breaches/" | fetch | resolve -%}
{% for breach in breaches %}
- {{ breach.Name }}
{% endfor %}

But I'm fascinated by the async fetch filter. Instead of node-fetch, I'd see if you could wrap it in the clever https://www.11ty.dev/docs/plugins/cache/ module for better caching/performance. Still not sure if it'd work better as a global data file, or if there are benefits to being able to fetch arbitrary URLs on demand.

@cfjedimaster
Copy link
Author

Well to be clear, I get the error even w/o fetch stuff (more on that in a sec). Using the document trivial setTimeout one, I get the error.

As for fetch... heh well it's more me playing around with an idea that's possibly not sensible - page level data fetching. I got the idea from Astro. I'm NOT saying it's a good idea, just something I wanted to build for fun. I actually got that idea working, so this is just now an issue w/ Nunjucks and the set tag I guess.

@zachleat
Copy link
Member

Yeah, I think async filters are working fine here but you’ve hit a Nunjucks edge case with set.

Try using the Eleventy provided Nunjucks shortcode for setAsync: #2108 (first available in Eleventy 1.0.1)

I would also note here that 2.0.0-canary.15 adds support for async filters in Nunjucks via the standard addFilter API too! #2536 See https://www.11ty.dev/docs/filters/#asynchronous-universal-filters

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants