【问题标题】:Q: chain callbacksQ:链式回调
【发布时间】:2015-07-23 20:54:29
【问题描述】:

我正在尝试按特定顺序运行回调。

基本上我有一个gulp 任务,它接收一个包含四个 CSS 路径的数组。我需要缩小每个文件并打印有关进度的状态。类似的东西:

Minifying file AAA.css: OK
Minifying file BBB.css: OK
Minifying file CCC.css: FAIL
Minifying file DDD.css: OK

首先我写了Minifying file AAA.css,所以我运行了一些gulp 方法,然后on("end")on("error") 应该分别用OK\nFAIL\n 完成短语。

我的问题是它正在打印类似于:

Minifying file AAA.css: Minifying file BBB.css: {...} DDD.css: Finished {...}.
OK
OK
FAIL
OK

这就是我尝试做的:

gulp.task("watch", function () {
    var files = [ "AAA.css", "BBB.css", "CCC.css", "DDD.css" ]; 
    var promise = Q();

    underscore.each(files, function (file) {
        minify(promise, file);
    });

    return promise;
});

function minify(promise, file) {
    promise.then(function() { write("Minifying " + file + ": ") });
    promise.then(function() {
        return gulp.src(file).{...}
            .on("error", function() { write("FAIL"); }) 
            .on("end", function() { write("OK"); }) 
    });
}

我尝试使用 Q.defer() 并为循环中的每个文件创建一个承诺,但没有成功......喜欢:

function minify(file) {
    var promise = Q();
    promise.then(function() { write("Minifying " + file + ": ") });
    promise.then(function() {
        return gulp.src(file).{...}
            .on("error", function() { write("FAIL"); }) 
            .on("end", function() { write("OK"); }) 
    });

    return promise();
}

我该怎么办?也许 Promise 或 Deferred 不能解决我的问题?

编辑:我当前的代码是http://pastebin.com/tSaXH1iF

【问题讨论】:

  • 所以你想放弃并行运行它们?
  • 我不在乎 BBB.css 是否在 AAA.css 之前缩小,但输出需要像 Min BBB: OK... Min AAA: OK...

标签: node.js promise gulp q


【解决方案1】:

问题是常见的异步问题:gulp.src() 将在您打印“缩小...”后很久才能完成。解决方案是在打印“Minifying...”消息之前等待它完成:

function minify(file) {
    var promise = Q();
    promise.then(function() {
        return gulp.src(file).{...}
            .on("error", function() { write("Minifying " + file + ":FAIL"); }) 
            .on("end", function() { write("Minifying " + file + ":OK"); }) 
    });

    return promise();
}

除非您想使用一些花哨的终端技巧将光标移动到正确的行以打印“OK”或“FAIL”,否则真的没有简单的方法。

【讨论】:

  • 考虑一下,最初,我想按顺序打印(AAA、BBB、...)。我想告诉用户我将开始缩小 CSS,并且,asyncly 告诉用户它是 OK 还是 FAIL。基本上:对于每个 CSS,打印构建消息,等待构建,打印构建状态消息,前进到下一个。
  • @DavidRodrigues:就像我说的,没有简单的方法可以做到这一点。也就是说,使用简单的console.log()write() 是无法做到这一点的。那是因为在您打印下一个“缩小...”之后,提示已经在下一行。做你想做的事情的唯一方法是将光标移动到确切的坐标以便打印正确的东西。这不是微不足道的。看npm上的terminal-control或者blessed包来控制终端(当然还有其他的库)。但是此时您基本上是在编写一个控制台应用程序,远远超出了 gulp 文件的应有范围。
【解决方案2】:

基于 slebetman 的回答,我认为您没有正确构建承诺(除非 gulp.src 返回承诺),您的代码可以工作,但在当前状态下,承诺无效。

使用Q.defer,您可以像这样承诺管道:

function minify(file) {
    var deferred = Q.defer();
    gulp.src(file).{...}
        .on("error", function(err) { write("Minifying " + file + ": FAIL"); deferred.reject(err);}) 
        .on("end", function() { write("Minifying " + file + ": OK");deferred.resolve(); });
    return promise();
}

【讨论】:

  • 我猜gulp.src 返回一个流。 Stream 与 Promise 有什么不同?我试试你的方法。谢谢。
【解决方案3】:

我终于找到了错误。基本上,.then() 会期待一个“承诺工厂”,而不是“承诺实例”。


我错误地运行了函数minifyCSS(),而不是将它绑定到.then()

缩小 CSS 函数:是正确的。我在它上面创建了一个延迟并返回它的承诺。

var deferred = Q.defer();

gulp.src(...)
    .pipe(...)
    .on("end", ... deffered.resolve() ...);

return deferred.promise;

之前:

var promise = Q();

promise.then( ... start message ... );
promise.then(minifyCSS(file)); 

return promise;

之后:

var promise = Q();

promise.then( ... start message ... );
promise.then(minifyCSS.bind(null, file)); 

return promise;

请注意每个示例中的第二个 .then() 调用。

一个小的逻辑错误。当我在第一个示例中调用 minifyCSS() 时(之前),Gulp 立即执行,而不是在最后一个 .then() 完成之后执行(就像在 after 中一样)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-09
    • 2012-10-16
    • 2013-02-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-12
    • 1970-01-01
    相关资源
    最近更新 更多