非同期完了#

Nodeライブラリは、さまざまな方法で非同期処理を扱います。最も一般的なパターンはエラーファーストコールバックですが、ストリームPromiseイベントエミッター子プロセス、またはObservableに出会うかもしれません。Gulpタスクは、これらすべてのタイプの非同期処理を正規化します。

タスク完了の通知#

ストリーム、Promise、イベントエミッター、子プロセス、またはObservableがタスクから返されると、成功またはエラーは、続行するか終了するかを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();
// Emitは、gulpがまだリッスンしていない場合は非同期に行う必要があります
setTimeout(() => emitter.emit('finish'), 250);
return emitter;
}
exports.default = eventEmitterTask;

子プロセスを返す#

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

Observableを返す#

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('kaboom'));
}
exports.default = callbackError;

ただし、多くの場合、このコールバックを自分で呼び出すのではなく、別の API に渡すことになります。

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

同期タスクは不可#

同期タスクはサポートされなくなりました。それらは、タスクからストリームを返すのを忘れるなど、デバッグが難しい微妙な間違いにつながることがよくありました。

「非同期完了のシグナルを忘れていませんか?」という警告が表示された場合、上記のいずれのテクニックも使用されていません。問題を解決するには、エラーファーストコールバックを使用するか、ストリーム、プロミス、イベントエミッター、子プロセス、またはオブザーバブルを返す必要があります。

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('some result');
}
exports.default = asyncAwaitTask;