Обещанию модуля NodeJS del требуется явная функция для обещания?

Я не понимаю, почему этой функции del нужна новая функция для ее обещания. Ниже приведен полный код. Проблема в функции очистки.

gulp.task('styles', ['clean-styles'], function () {
log('Compiling less to css');

return gulp
    .src(config.less)
    .pipe($.less())
    .pipe($.autoprefixer({browsers: ['last 2 version', '> 5%']}))
    .pipe(gulp.dest(config.temp));

});

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

gulp.task('less-watcher', function () {
    gulp.watch([config.less], ['styles']);
});

////////////////

function clean(path, done) {
    log('Cleaning: ' + $.util.colors.blue(path));

    console.log(typeof done); // prints 'function'
    del([path]).then(done); // errors
}

function log(msg) {
    if (typeof msg === 'object') {
        for (var item in msg) {
            if (msg.hasOwnProperty(item)) {
                $.util.log($.util.colors.blue(msg[item]));
            }
        }
    } else {
        $.util.log($.util.colors.blue(msg));
    }
}

Это ошибка, которую я получаю:

[23:28:32] Using gulpfile ~/WebstormProjects/gulp-tutorial/gulpfile.js
[23:28:32] Starting 'clean-styles'...
[23:28:32] Cleaning: ./.temp**/*.css
function
[23:28:32] 'clean-styles' errored after 36 ms
[23:28:32] Error    
at formatError (/usr/lib/node_modules/gulp/bin/gulp.js:169:10)    
at Gulp.<anonymous> (/usr/lib/node_modules/gulp/bin/gulp.js:195:15)    
at emitOne (events.js:96:13)    
at Gulp.emit (events.js:188:7)    
at Gulp.Orchestrator._emitTaskDone (/home/user/WebstormProjects/gulp-tutorial/node_modules/orchestrator/index.js:264:8)    
at /home/user/WebstormProjects/gulp-tutorial/node_modules/orchestrator/index.js:275:23    
at finish (/home/user/WebstormProjects/gulp-tutorial/node_modules/orchestrator/lib/runTask.js:21:8)    
at cb (/home/user/WebstormProjects/gulp-tutorial/node_modules/orchestrator/lib/runTask.js:29:3)

Если я изменю код для «чистой» функции, как показано ниже, это странным образом решит проблему. Почему он отвергает одну функцию, но принимает другую?

function clean(path, done) {
    log('Cleaning: ' + $.util.colors.blue(path));

    console.log(typeof done); // prints 'function'
    del([path]).then(function () {
        done(); // works!
    });
}

Даже если я использую функцию, которая была назначена переменной, а не поднята, она все равно работает. Итак, почему он не принимает функцию «готово» в обещании. Это сбивает с толку мой мозг.

function clean(path, done) {
    log('Cleaning: ' + $.util.colors.blue(path));

    console.log(typeof done); // prints 'function'
    var test = function () {
        done();
    }
    del([path]).then(test);
}

----------РЕШЕНО----------

Спасибо Йоханнесу Мерцу за ответ на этот вопрос. Я думал о функции «готово» как об обратном вызове, но ошибся. Он принадлежит gulp, поэтому, чтобы смоделировать проблему, воспользуйтесь новой «чистой» функцией ниже.

function clean(path, done) {
    log('Cleaning: ' + $.util.colors.blue(path));

    del([path]).then(function (val) {
        console.log(val);
        done('Not null or undefined so this will fail it');
        // done(); but this would work!
    });
}

В основном обещание передаст аргумент функции, используемой обещанием. Это все портит, потому что обратный вызов 'done' считает, что аргумент является сообщением об ошибке или объектом. Теперь это имеет для меня смысл.

done(err);

Поэтому, если 'err' имеет значение null или undefined, у нас не будет проблем. Проблема в том, что промис этого не знает. Обещание передает сообщение, а не ошибку, но функция done считает, что это ошибка, поэтому она выдает ошибку.

Задача решена :)


person JamesD    schedule 17.03.2017    source источник


Ответы (1)


Это потому, что функция del разрешает обещание со значением. Взгляните на документы, сделанное считается успешным, если оно прошло неопределенное:

https://github.com/gulpjs/gulp/blob/master/docs/API.md#accept-a-callback

Таким образом, вы вызываете done('some value that isn't undefined'), если вы передаете done в блок then напрямую, что считается ошибкой, тогда как вы вызываете done();, если вы заключаете его в дополнительную функцию. Пытаться

del([path]).then(function (delResult) {
    console.log(delResult);
    done(); // works!
});

посмотреть, что вернулось.

person Johannes Merz    schedule 17.03.2017
comment
Вау, это сбивало с толку. Я прочитал этот ответ около 20 раз, пытаясь понять его. Параллелизм и асинхронные проблемы всегда ловят меня. Спасибо за помощь! - person JamesD; 18.03.2017