3

I am very new to Promises, but would like to use them to sequentially fire off a clean (deleting files) and then a make (copying files from source to build).

gulp.task('make-app', function makeApp(done) {
    function make() {
        return gulp.src(getPatterns('src-app'))
            .pipe(gulp.dest('./build/app/'));
    }

    return (args.noclean && !args.deploy)
        ? make()
        : del(getPatterns('dest-app')
            .then(make);
            // .then(done);
});

Some things to note:

getPatterns() is a function which simply returns a glob pattern from my config. The src-app glob is: [ './source/app/**/*' ]. The (args.noclean && !args.deploy) evaluate to false, which starts the del module (which is v2, so it returns a Promise). To my limited understanding of Promises, we .then() it to the make() function, which I'd love to return a Promise and just chain a .then(done), but that's where I'm lost. Currently, I'm just returning a stream, which is resulting in not all the files copying over.

UPDATE

I've taken about 70 more random stabs (the absolute, most miserable way to gain experience!) and have come up with this:

return del(getPatterns('dest-app'))
    .then(function() {
        return gulp.src(getPatterns('src-app'))
            .pipe(gulp.dest(dest + app));
    });

And the build process completes, the files always get deleted first, but Gulp only copies over the first 16 files/folders from the stream.

UPDATE 2 - The below code LOOKS as if it'd work, but Gulp reports that it is not completing (so a Stream, Promise or Callback is not being returned).

var make = new Promise(function(resolve, reject) {});        
var clean = del(getPatterns('dest-app'))
    .then(function() {
        var makeStream = gulp.src(getPatterns('src-app'))
            .pipe(gulp.dest(dest + app));
        makeStream.on('end', function() {
            make.resolve();
        });
    });

return Promise.all([clean, make]);
Aaron Martone
  • 61
  • 1
  • 6
  • I don't see any difference between your first and second snippet (except in the first, `del(` is missing a closing parenthesis) – Bergi Oct 17 '15 at 16:05
  • Oh man,that's funny. All that wasted time only to come around to the original problem BUT with the realization that it deletes the files, but only copies over the first 16 files. Often, when I see myself wasting hours and days on a problem, I tell myself to take different angles at the approach; but that logic won't work because one of the core issues here is that I don't comprehend, at a low level, how Promises work, nor how Gulp 4 handles multiple asynchronous actions to prevent them from stepping on each other. – Aaron Martone Oct 17 '15 at 16:18
  • I've been doing some research and many people are stating that the limiting to acting on 16 files in the stream is a default behavior of `fs-vinyl` (which I have never seen before) and that in order to fix the issue I have to "sink the stream". After researching what the heck that phrase meant, they state "simply return the `gulp.src(...)`. Gulp 4 does not allow sync tasks, of the acceptable returns, it can take a `callback`, `Promise` or a `Stream`. My current implementation must not be returning the stream, because it's stopping @ 16 files copied. – Aaron Martone Oct 18 '15 at 13:43
  • Then probably the reason is that you cannot return a stream from the promise `then` callback - it only works with promises. So try to convert the stream to a promise, like [here](http://stackoverflow.com/a/30082502/1048572) or [here](http://stackoverflow.com/a/29722640/1048572), so that `make` returns a promise. – Bergi Oct 18 '15 at 13:52
  • So what we're saying is that `Promise` is a future value, but ultimately if we choose to return it, then we cannot return the callback/stream (other 2 acceptable return types of a task). So my choices are to either make cleaning and making separate promises (`del` already supports promises, so I'd have to find a way to either convert the copy stream to a Promise) so that I could just return the `Promise.all()` of both. – Aaron Martone Oct 19 '15 at 12:27
  • Well, I'm giving up. As pivotal in my self-education as it is to learn Gulp, there simply are no low level resources out there to do so. A person can only spend so many days of time before the urge to make actual progress somewhere triumphs over the inability to find the understanding I was seeking. So I'll just create 2 separate tasks, and call them in series. On the first attempt in doing so, all files were deleted from the directory, and 100% (rather than the mystical first 16) were copied over. It's more tasks but at this point I simply don't care. lol. Much appreciation to all. – Aaron Martone Oct 19 '15 at 13:29

2 Answers2

4

No, your update 2 doesn't look like it should be working. make is promise and has no resolve method that you could call, instead you'd need to call the resolve function that is given to your constructor callback. In your version, make (and the returned Promise.all) never resolve.

This is how it should look like:

function make() {
    return new Promise(function(resolve, reject) {
        gulp.src(getPatterns('src-app'))
        .pipe(gulp.dest('./build/app/'))
        .on("end", resolve)
        .on("error", reject);
    });
}

return (args.noclean && !args.deploy)
    ? make()
    : del(getPatterns('dest-app')).then(make);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • In Gulp 4, that solution doesn't seem to complete. (which to my understanding means that it never returns a Stream, Promise or Callback from the Task function itself. It deletes the files (per the `del()` Promise) and then fires off the `make()` function (but only copies the first 16 files/folders) and then never returns out of the task function to continue. – Aaron Martone Oct 19 '15 at 18:47
  • Hm, it *does* return a promise for the result of `make` (after `del()` has finished) to the task. – Bergi Oct 19 '15 at 19:08
  • So promises are future values right? When make() creates a new Promise that resolves, is a value being returned to the task's definition function? I think that's what Gulp 4 would be looking for as far as its returned value. The initial `return` returns the promise returned from the `del` which resolves to run `make()` (so Gulp's initial returned Promise resolved, despite it executing a function that creates another Promise to copy files over whose `resolve` is not defined and just marks the promise as resolved. – Aaron Martone Oct 19 '15 at 20:09
  • No, the initial `return` doesn't return the `del()` promise, it returns the promise that is returned by the `.then(…)` call. Which resolves with the same value as the promise returned by the callback (`make`). There is nothing wrong with the promises here, if it's still not working then it must be the stream-to-promise conversion. – Bergi Oct 19 '15 at 20:17
  • OK. So the last value that the initial promise returns is the value that is ultimately returned from the promise? Can I ask what version of Gulp you're using to test this? I think one of the main differences between 3.x and 4.x is that 4 no longer allows synchronous returns, otherwise the task never ends, which seems to be the issue I'm getting with the above code. – Aaron Martone Oct 19 '15 at 20:51
  • The result value of the initial promise is what is passed to the `then` callback. The ultimately returned promise resolves with the return value from the callback of the last `then` call in the chain (and when the promise resolves with a promise, it will be unwrapped). I didn't actually test this, I was just fixing your promise usage :-) – Bergi Oct 19 '15 at 20:54
0

How to use Promise:

var newPromise = new Promise (function (resolve, reject) {
    gulp.src(getPatterns('src-app')) // path on which you want to work 
    .pipe(gulp.dest('./build/app/')) // pipe the task that you want to run here i am copying 
    .on('end', resolve)
    .on('error', reject);
});

newPromise
    .then(function () {
        // Do something after promise is completed
        // This will be run after promise is resolved or success
    })
    .catch(function () {
        console.log("Error");
    });
Anushil Kumar
  • 674
  • 8
  • 8