跳到主要内容

异步完成

Node 库以各种方式处理异步性。最常见的模式是错误优先回调,但你也可能遇到承诺(Promise)事件发射器子进程可观察对象。Gulp 任务能够规范化所有这些类型的异步性。

任务完成信号

当从任务中返回流、承诺、事件发射器、子进程或可观察对象时,成功或错误的结果会告知 gulp 是继续还是终止。如果任务出错,gulp 将立即终止并显示该错误。

当使用 series() 组合任务时,发生错误会终止整个组合,不会执行后续任务。当使用 parallel() 组合任务时,发生错误会终止组合,但其他并行任务可能会也可能不会完成。

返回流

const { src, dest } = require('gulp');

function streamTask() {
return src('*.js')
.pipe(dest('output'));
}

exports.default = streamTask;

返回承诺(Promise)

function promiseTask() {
return Promise.resolve('返回的值会被忽略');
}

exports.default = promiseTask;

返回事件发射器

const { EventEmitter } = require('events');

function eventEmitterTask() {
const emitter = new EventEmitter();
// 发射必须异步进行,否则 gulp 尚未开始监听
setTimeout(() => emitter.emit('finish'), 250);
return emitter;
}

exports.default = eventEmitterTask;

返回子进程

const { exec } = require('child_process');

function childProcessTask() {
return exec('date');
}

exports.default = childProcessTask;

返回可观察对象

const { Observable } = require('rxjs');

function observableTask() {
return Observable.of(1, 2, 3);
}

exports.default = observableTask;

使用错误优先回调

如果你的任务没有返回任何内容,则必须使用错误优先回调来表示完成。回调将作为唯一的参数传递给你的任务 - 在下面的示例中名为 cb()

function callbackTask(cb) {
// `cb()` 应当被某些异步工作调用
cb();
}

exports.default = callbackTask;

要在使用错误优先回调的任务中向 gulp 指示发生了错误,请以 Error 作为唯一参数调用它。

function callbackError(cb) {
// `cb()` 应当被某些异步工作调用
cb(new Error('出错了'));
}

exports.default = callbackError;

然而,你通常会将此回调传递给另一个 API,而不是自己调用它。

const fs = require('fs');

function passingCallback(cb) {
fs.access('gulpfile.js', cb);
}

exports.default = passingCallback;

不再支持同步任务

不再支持同步任务。它们经常导致难以调试的细微错误,比如忘记从任务中返回流。

当你看到 "Did you forget to signal async completion?" 警告时,这意味着未使用上述任何技术。你需要使用错误优先回调或返回流、承诺、事件发射器、子进程或可观察对象来解决此问题。

使用 async/await

当不使用之前的任何选项时,你可以将任务定义为 async 函数,它会将你的任务包装在承诺中。这允许你使用 await 同步地处理承诺,并使用其他同步代码。

const fs = require('fs');

async function asyncAwaitTask() {
const { version } = JSON.parse(fs.readFileSync('package.json', 'utf8'));
console.log(version);
await Promise.resolve('某些结果');
}

exports.default = asyncAwaitTask;