anandthakker / doiuse

:bomb: Lint CSS for browser support against caniuse database.
MIT License
1.25k stars 51 forks source link

running the API against multiple files #12

Closed dominikwilkowski closed 9 years ago

dominikwilkowski commented 9 years ago

Hey again.

I've been using this excellent library to learn a bit more about streams in node. I set out to create a grunt plugin for this but I'm running into a lot of corners with the stream approach.

Essentially grunt gives us a lot of files in a nested array. Now I work with promises to resolve the callback hell I would otherwise get.

var done = this.async();

this.files.forEach(function targetLoop( files ) {

    //run DoIUse
    var promises = files.src.map(function(file) {
        return new Promise(function(resolve, reject) {

            Fs
                .createReadStream(file)
                .pipe( new Doiuse( OPTIONS.browsers ) )
                .on('data', resolve)
                .on('error', reject);

        });
    });

    Promise
        .all(promises)
        .then(function(usageInfos) {
            console.log("all of them done", usageInfos);

            done(true);
        }, function(err) {
            console.error("(At least) one of them failed", err);

            done(true);
        });

});

This unfortunately returns [css-tokenize] unfinished business [ [ 'root' ] ] and fails. Any hint on what to archive this? I've been asking on stackoverflow too but I think this might be an issue directly related to your lib.

anandthakker commented 9 years ago

@dominikwilkowski The [css-tokenize] warning is a red herring here--bad design on my part to have this be printed to the console, but it's just a warning so I don't think it's related to your problem.

One thing I see in your example above is that it's treating new Doiuse(...) as though it would only emit a single data event, with all the feature infos for that file as a single usageInfos object. In fact, the data event will happen once for each feature in the file, so you can't just use that event to resolve your promise. Instead, if you want to do it this way, you'll need to collect all the usages, and then resolve the promise when the stream ends... something like this:

    var promises = files.src.map(function(file) {
        return new Promise(function(resolve, reject) {

            var usageInfos = [];

            Fs
                .createReadStream(file)
                .pipe( new Doiuse( OPTIONS.browsers ) )
                .on('data', function (info) { usageInfos.push(info); })
                .on('end', function () { resolve(usageInfos); })
                .on('error', reject);
        });
    });
dominikwilkowski commented 9 years ago

Thanks @anandthakker That's what I've been looking for. I was on that track but didn't had time to look further into it.

Now how do I suppress that unfinished business output? :)

ps grunt plugin code here: https://github.com/dominikwilkowski/grunt-doiuse

anandthakker commented 9 years ago

@dominikwilkowski The console warning is due to https://github.com/anandthakker/css-tokenize/issues/1 -- I'm going to close this here.