异步完成#

¥Async Completion

节点库以多种方式处理异步性。最常见的模式是 错误优先回调,但你也可能会遇到 streamspromises事件触发器子进程observables。Gulp 任务规范了所有这些类型的异步性。

¥Node libraries handle asynchronicity in a variety of ways. The most common pattern is error-first callbacks, but you might also encounter streams, promises, event emitters, child processes, or observables. Gulp tasks normalize all these types of asynchronicity.

信号任务完成#

¥Signal task completion

当从任务返回流、Promise、事件触发器、子进程或可观察对象时,成功或错误会通知 gulp 是继续还是结束。如果任务出错,gulp 将立即结束并显示该错误。

¥When a stream, promise, event emitter, child process, or observable is returned from a task, the success or error informs gulp whether to continue or end. If a task errors, gulp will end immediately and show that error.

当使用 series() 组合任务时,出现错误将结束组合并且不会执行进一步的任务。当使用 parallel() 组合任务时,错误将结束组合,但其他并行任务可能会完成,也可能不会完成。

¥When composing tasks with series(), an error will end the composition and no further tasks will be executed. When composing tasks with parallel(), an error will end the composition but the other parallel tasks may or may not complete.

返回流#

¥Returning a stream

const { src, dest } = require('gulp');
function streamTask() {
return src('*.js')
.pipe(dest('output'));
}
exports.default = streamTask;

返回 promise#

¥Returning a promise

function promiseTask() {
return Promise.resolve('the value is ignored');
}
exports.default = promiseTask;

返回事件触发器#

¥Returning an event emitter

const { EventEmitter } = require('events');
function eventEmitterTask() {
const emitter = new EventEmitter();
// Emit has to happen async otherwise gulp isn't listening yet
setTimeout(() => emitter.emit('finish'), 250);
return emitter;
}
exports.default = eventEmitterTask;

返回子进程#

¥Returning a child process

const { exec } = require('child_process');
function childProcessTask() {
return exec('date');
}
exports.default = childProcessTask;

返回可观察对象#

¥Returning an observable

const { Observable } = require('rxjs');
function observableTask() {
return Observable.of(1, 2, 3);
}
exports.default = observableTask;

使用错误优先回调#

¥Using an error-first callback

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

¥If nothing is returned from your task, you must use the error-first callback to signal completion. The callback will be passed to your task as the only argument - named cb() in the examples below.

function callbackTask(cb) {
// `cb()` should be called by some async work
cb();
}
exports.default = callbackTask;

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

¥To indicate to gulp that an error occurred in a task using an error-first callback, call it with an Error as the only argument.

function callbackError(cb) {
// `cb()` should be called by some async work
cb(new Error('kaboom'));
}
exports.default = callbackError;

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

¥However, you'll often pass this callback to another API instead of calling it yourself.

const fs = require('fs');
function passingCallback(cb) {
fs.access('gulpfile.js', cb);
}
exports.default = passingCallback;

无同步任务#

¥No synchronous tasks

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

¥Synchronous tasks are no longer supported. They often led to subtle mistakes that were hard to debug, like forgetting to return your streams from a task.

当你看到 "你是否忘记触发异步完成信号?" 警告时,表明上述技术均未使用。你需要使用错误优先回调或返回流、promise、事件触发器、子进程或可观察对象来解决问题。

¥When you see the "Did you forget to signal async completion?" warning, none of the techniques mentioned above were used. You'll need to use the error-first callback or return a stream, promise, event emitter, child process, or observable to resolve the issue.

使用异步/等待#

¥Using async/await

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

¥When not using any of the previous options, you can define your task as an async function, which wraps your task in a promise. This allows you to work with promises synchronously using await and use other synchronous code.

const fs = require('fs');
async function asyncAwaitTask() {
const { version } = JSON.parse(fs.readFileSync('package.json', 'utf8'));
console.log(version);
await Promise.resolve('some result');
}
exports.default = asyncAwaitTask;