postcss / postcss-load-config

Autoload Config for PostCSS
MIT License
644 stars 73 forks source link

How to use async function? #212

Open gavinmcfarland opened 3 years ago

gavinmcfarland commented 3 years ago

I've never been able to successfully use the async API in my application and I'm wondering why? Do you have any thoughts?

I'm using:

async function processPostCSS(src = '') {
    const ctx = { parser: true, map: 'inline' };

    const { plugins } = await postcssrc(ctx)
    const { css } = await postcss([postcssNested(), autoprefixer(), ...plugins]).process(src, { from: undefined })

    return css
}

postcssrc(ctx) causes this function to break for some reason that I don't understand. If I change to the synchronous API it works fine. I'm not sure how to tell what the error is, all I know is that it doesn't return the css when I use the postcss-load-config async API

What am I doing incorrectly?

RyanZim commented 3 years ago

Does the promise returned by processPostCSS resolve or reject at all, or does it hang?

gavinmcfarland commented 3 years ago

Sorry for not providing more info with error messages etc. I've been having a real tough time diagnosing it because I'm only just starting to understand properly how promises work and also there must be some caching issues because sometimes (rarely) I'll run the build and it appears to work (pretty sure not caused by promise).

So I was able to add a catch to all processPostCSS calls and it returns the error TypeError: plugins is not iterable When I did a console.log(plugins) it returns undefined.

Any idea of how I diagnose what postcssrc() is doing in this particular scenario?

gavinmcfarland commented 3 years ago

Sorry this was is my bad. I had missed the await keyword when testing it again (switching from sync to async). Unfortunately, I cannot get any error from processPostCSS. To confirm, it doesn't reject or resolve anything or hang.

RyanZim commented 3 years ago

To confirm, it doesn't reject or resolve anything or hang.

It has to be doing something. A promise can either be pending, resolved, or rejected. Only those three states. If it's still pending after a reasonable amount of time, it's probably hanging.

gavinmcfarland commented 3 years ago

That's what I thought, I'm using postcss-tape to test the plugin and it's not returning any error messages apart from the test failing. I can only imagine that it must be suppressing any error messages. I'll have to create a standalone test script to see if it produces any error messages.

gavinmcfarland commented 3 years ago

I think what is happening is as soon as I add the await for postcssrc() it means that the result of that promise doesn't occur until the whole plugin has already finished. This leads me to believe although it appears like it's postcssrc() which is causing it to break because it works with postcssrc.sync(), its simply just because the promise has something to resolve and thefore completing after the rest of the script. Which I think any promise would have the same effect.

What I don't know now is how to resolve geting the config file before any of the rest of the code runs. I'm trying to get it to work with a HTML processor I created but I'm struggling to think how I have to write the async functions to get postcss-load-config to resolve before the rest of the plugin begins. This is the main file https://github.com/limitlessloop/stylup/blob/master/src/index.js where postcss-load-config is used. If you have any suggestions for how I can get it work properly that would be helpful, but realise this is now probably not a use case unique to postcss-load-config.

gavinmcfarland commented 3 years ago

I've had time to look at this a bit, and I think I now realise that in order to be able to use the async version of the API the framework I'm using would have to be able to accept a promise which is why I can't get this to work. I've since gone back to using the synchronous version of the API and added a try-catch block to detect if a config file has been found or not.

var plugins;

try {
    plugins = { plugins } = postcssrc.sync(ctx)
catch (error) {
    plugins = []
}

const { css } = await postcss([postcssNested(), autoprefixer(), ...plugins]).process(src, { from: undefined })