简体   繁体   中英

What is the meaning of using done as a parameter in a javascript function?

i am learning Javascript, and it seems that the done as a parameter in a function is a difficult concept to understand. I want to know why it does behaves like that (done as a parameter (completed process signal i guess), and if there is some good book or resource Online to study further this concept. Example , i am following along with a Tutorial and it uses done as a parameter, the thing is that when i run the code on node via gulp (gulpfile.js) the process never stops when using done, if i choose to skip done in the code it runs smoothly. I am trying to track down the problem, and i know that the problem is the done as a parameter, ( it has been checked by me multiple times).

gulp.task('clean-styles', function(done) {
    var files = config.temp + '**/*.css';
    clean(files, done);
});


function clean(path, done) {
    log('Cleaning: ' + $.util.colors.blue(path));
    del(path, done).then(function(path) {
        console.log("path=",util.inspect(path,false,null))
        console.log('Deleted Files\/Folders:\n', path.join('\n'));
        console.log('Finishing clean')
    });
}
  • node version: 0.12.4
  • npm version: 2.10.1
  • gulp version: 3.9.0

Thanks a lot for any help, it will be really appreciated. Salutations.

can only explain the concept. what you are trying to achieve is not clear enough.

done is just a non-official standard name for a function (aka callback) that informs the calling function (parent in stacktrace) that a task is completed.

recall that javascript is asynchronous and functions can be passed around as variables.

now, imagine a function startPrinting that has to call printText1 , printText2 and printText3 and then output message that process is completed. We have:

function startPrinting() {
    printText1();
    printText2();
    printText3();
    console.log("completed");
}
function printText1() {
    $.get('http://ps-web.cloudapp.net/proxy.php?url=http://pastebin.com/raw.php?i=3uPCavLN', function(response){
        console.log(response)
    });
}
function printText2() {
    $.get('http://ps-web.cloudapp.net/proxy.php?url=http://pastebin.com/raw.php?i=jZjqKgNN', function(response){
        console.log(response)
    });
}
function printText3() {
    $.get('http://ps-web.cloudapp.net/proxy.php?url=http://pastebin.com/raw.php?i=SreCbunb', function(response){
        console.log(response)
    });
}

here, there is no assurance that completed will ALWAYS be printed after all three functions have been executed. since they execute asynchronously.

in order to sort this, javascript ninjas will introduce a done function so that startPrinting will only print completed when all three functions have been executed. Notice how a function is passed to printText1 ... 2 below:

function startPrinting() {
    /* START OF DONE ROUTINE */
    var count = 0;
    var printCompleted = function() {
        count+=1;

        if(count == 3)
            console.log("completed");
    }
    /* END */
    printText1(printCompleted);
    printText2(printCompleted);
    printText3(printCompleted);
}
function printText1(done) {
    $.get('http://ps-web.cloudapp.net/proxy.php?url=http://pastebin.com/raw.php?i=3uPCavLN', function(response){
        console.log(response)
        done();
    });
}
function printText2(done) {
    $.get('http://ps-web.cloudapp.net/proxy.php?url=http://pastebin.com/raw.php?i=jZjqKgNN', function(response){
        console.log(response)
        done();
    });
}
function printText3(done) {
    $.get('http://ps-web.cloudapp.net/proxy.php?url=http://pastebin.com/raw.php?i=SreCbunb', function(response){
        console.log(response)
        done();
    });
}

I hope you are able to apply this principle to better understanding your context.

Functions are first class objects in JavaScript. You can pass them around like any other value. Once they have been passed to another function as an argument, then you can call them using the argument name (or call another function and pass them as an argument to that, or assign them properties, or convert them to strings, or whatever else you'd like to do with them).

 function this_sets_the_body() { document.body.innerHTML = "Hello, world"; } function this_calls_a_callback(im_a_callback) { im_a_callback(); } this_calls_a_callback(this_sets_the_body); 

In your code, you've written a function using an anonymous function expression:

 function(done) { // ... } 

… and you've told it to expect to be called with an argument which you are calling done .

Whatever value is passed to it, you are ignoring (your function doesn't mention done after the argument name).

The library you are using (presumably) is passing a function in there and expects you to call it once your function as done whatever it is that it is going to do. This lets it wait until anything asynchronous that you are doing is finished.

So call done() when your code is done.

It looks like your example is fully messed up with respect to callbacks. In some places in your example done is used as a callback -- a function given from outside to be called when everything is finished in an asynchronous process and signal the end of the operation. In other cases it looks to be used as an argument provided by the execution method itself. In yet another you use it in a promise . Anyway, as I am not familiar with gulp I can only guess, but I hope the following example would work for you to explain the concepts of callback and partially promise . I would, however, recommend to avoid situations of missing callbacks and promises in the same code as it leads to confusion.

gulp.task('clean-styles', function(done) {
   console.log(1);
   /* we are in the callback of gulp.task: we give the
    * latter this anonymous function to call when the 
    * setup is ready and it gives us function done to
    * call when we are done and signal the engine any errors
    */
   var files = config.temp + '**/*.css';

   /* this defines the action to take when files are actually deleted */
   var callback = function(err, message) {
       console.log(6);
       console.log(message); // expect: looks good
       // this is provided apparently by gulp and calling it signals the engine that everything is completed
       done(err);
   };

   /* we call this function, but some bits (like deletion 
    * run asynchronously. The function will return quickly, but
    * callback (function) will only be called when files are deleted */
   clean(files, callback);
   /* the execution of gulp.task callback is finished,
    * but files are not yet deleted */
   console.log(4);
});

/* done here is not the same done as above, it is actually
 * the function we supply into the call above, i.e. `callback` */
function clean(path, done) {
    /* the cleanup is starting */
    console.log(2);
    /* del is scheduled. it returns a `promise` and if
     * we call `then`, then the given anonymous function
     * will be executed when files are deleted. This is
     * where we call the provided function `done` to
     * signal that the job is complete and execute some action */
    del(path).then(function() {
        /* files are deleted and this callback is called */
        console.log(5);
        /* we let the outer caller know by calling `done` which
         * was given to us from outside */
        done(null, "looks good"); // null means no error
    }).catch(function(err) {
        done(err, "looks bad"); // err is given back
    });
    /* the clean method is through, but files not yet deleted */
    console.log(3);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM