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

add: make log filter async friendly by adding logAsync #3141

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Snapstromegon
Copy link
Member

Right now the log filter logs the passed in values directly. This isn't always helpful when working with async values e.g. in webc components. This change adds the logAsync filter to also take promises as any value and awaits them, so you always get some useful output.

It could be possible to just eagerly return the value in the sync filter and then use a .then call to log the values, but that would leave room for unexpected data mutation, so I didn't implement it that way for now.

resolves #3133

Right now the `log` filter logs the passed in values directly. This isn't always helpful when working with async values e.g. in webc components.
This change adds the `logAsync` filter to also take promises as any value and awaits them, so you always get some useful output.

It could be possible to just eagerly return the value in the sync filter and then use a `.then` call to log the values, but that would leave room for unexpected data mutation, so I didn't implement it that way for now.

Signed-off-by: Raphael Höser <[email protected]>
@zachleat
Copy link
Member

zachleat commented Jan 2, 2024

Can we test for promises in log and await instead? It might be preferable to make log async friendly in 3.0

@Snapstromegon
Copy link
Member Author

If we make the log filter itself async, it would no longer be available in languages that don't support async filters (like handlebars).

I've just seen that addFilter only adds the filters to Liquid, JavaScriptFunctions and Nunjucks filters, so we could make it indeed async for everything.

@zachleat
Copy link
Member

zachleat commented Apr 9, 2024

Ah, sorry—I meant (kind of) like this

config.addFilter("log", (...messages) => {
  // if any of messages are a promise, do promise things
  if(messages.find(entry => /* promise test */)) {
    // out of order, but that’s preferable to errors in non-async
    Promise.all(messages).then(msgs => console.log(...msgs));
  } else {
    console.log(...messages);
  }
});

some prior art (not exactly):

if (callback instanceof ComparisonAsyncFunction) {

@Snapstromegon
Copy link
Member Author

Ahh okay, I see what you mean and I will adapt it.

@Snapstromegon
Copy link
Member Author

Thinking about it, we could even return a promise if any of the inputs is async. That would also fix the ordering issue for async cases or am I missing something here?

@Snapstromegon
Copy link
Member Author

@zachleat are we intending to support only native Promises here, or also all "thenables" (so e.g. Bluebird promises and similar custom promise implementations)?
I think they would be detectable by testing if something has a .then() method, but that seems flaky too.

@zachleat
Copy link
Member

zachleat commented Apr 9, 2024

native promises only is fine. And I like the promise return! That wouldn’t work with our async filtering stuff though, since it checks if the callback is async (not the return value).

@Snapstromegon
Copy link
Member Author

@zachleat Good catch.

Since the removal of some of the built-in templating languages, is there a reason to not just add it via addAsyncFilter?

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

Successfully merging this pull request may close these issues.

Asynchronous filter returns a Promise object
2 participants