Lỗi Gulp: Các tác vụ sau không hoàn thành: Bạn đã quên báo hiệu hoàn thành async?


211

Tôi có gulpfile.js sau đây , mà tôi đang thực thi thông qua thông báo gulp dòng lệnh :

var gulp = require('gulp');

gulp.task('message', function() {
  console.log("HTTP Server Started");
});

Tôi nhận được thông báo lỗi sau:

[14:14:41] Using gulpfile ~\Documents\node\first\gulpfile.js
[14:14:41] Starting 'message'...
HTTP Server Started
[14:14:41] The following tasks did not complete: message
[14:14:41] Did you forget to signal async completion?

Tôi đang sử dụng gulp 4 trên hệ thống Windows 10. Đây là đầu ra từ gulp --version:

[14:15:15] CLI version 0.4.0
[14:15:15] Local version 4.0.0-alpha.2

1
Nếu bạn ở đây vì bạn có vấn đề với webpack-stream. Sử dụng cái này: github.com/shama/webpack-stream/issues/,
B3none

Câu trả lời:


447

Vì tác vụ của bạn có thể chứa mã không đồng bộ, bạn phải báo hiệu gulp khi tác vụ của bạn đã thực hiện xong (= "hoàn thành async").

Trong Gulp 3.x bạn có thể thoát khỏi mà không cần làm điều này. Nếu bạn không báo hiệu rõ ràng việc hoàn thành không đồng bộ, gulp sẽ chỉ cho rằng nhiệm vụ của bạn là đồng bộ và nó sẽ kết thúc ngay khi chức năng nhiệm vụ của bạn trở lại. Gulp 4.x chặt chẽ hơn về vấn đề này. Bạn phải báo hiệu rõ ràng nhiệm vụ hoàn thành.

Bạn có thể làm điều đó theo sáu cách :

1. Trả lại một luồng

Đây thực sự không phải là một lựa chọn nếu bạn chỉ cố gắng in một cái gì đó, nhưng có lẽ đó là cơ chế hoàn thành async được sử dụng thường xuyên nhất vì bạn thường làm việc với các luồng gulp. Đây là một ví dụ (khá giả) chứng minh nó cho trường hợp sử dụng của bạn:

var print = require('gulp-print');

gulp.task('message', function() {
  return gulp.src('package.json')
    .pipe(print(function() { return 'HTTP Server Started'; }));
});

Phần quan trọng ở đây là returntuyên bố. Nếu bạn không trả lại luồng, gulp không thể xác định khi nào luồng kết thúc.

2. Trả lại một Promise

Đây là một cơ chế phù hợp hơn nhiều cho trường hợp sử dụng của bạn. Lưu ý rằng hầu hết thời gian bạn sẽ không phải tự tạo Promiseđối tượng, nó thường sẽ được cung cấp bởi một gói (ví dụ: delgói được sử dụng thường xuyên trả về a Promise).

gulp.task('message', function() { 
  return new Promise(function(resolve, reject) {
    console.log("HTTP Server Started");
    resolve();
  });
});

Sử dụng cú pháp async / await, điều này có thể được đơn giản hóa hơn nữa. Tất cả các chức năng được đánh dấu asynchoàn toàn trả về một Promise để các chức năng sau cũng hoạt động (nếu phiên bản node.js của bạn hỗ trợ nó ):

gulp.task('message', async function() {
  console.log("HTTP Server Started");
});

3. Gọi chức năng gọi lại

Đây có lẽ là cách dễ nhất cho trường hợp sử dụng của bạn: gulp tự động chuyển một hàm gọi lại cho tác vụ của bạn làm đối số đầu tiên. Chỉ cần gọi chức năng đó khi bạn hoàn thành:

gulp.task('message', function(done) {
  console.log("HTTP Server Started");
  done();
});

4. Trả lại một quá trình con

Điều này chủ yếu hữu ích nếu bạn phải gọi trực tiếp một công cụ dòng lệnh vì không có trình bao bọc node.js khả dụng. Nó hoạt động cho trường hợp sử dụng của bạn nhưng rõ ràng tôi không khuyên dùng nó (đặc biệt là vì nó không dễ mang theo):

var spawn = require('child_process').spawn;

gulp.task('message', function() {
  return spawn('echo', ['HTTP', 'Server', 'Started'], { stdio: 'inherit' });
});

5. Trả lại một RxJSObservable .

Tôi chưa bao giờ sử dụng cơ chế này, nhưng nếu bạn đang sử dụng RxJS thì nó có thể hữu ích. Đó là loại quá mức nếu bạn chỉ muốn in một cái gì đó:

var of = require('rxjs').of;

gulp.task('message', function() {
  var o = of('HTTP Server Started');
  o.subscribe(function(msg) { console.log(msg); });
  return o;
});

6. Trả lại một EventEmitter

Giống như phần trước tôi bao gồm điều này vì mục đích hoàn chỉnh, nhưng nó không thực sự là thứ bạn sẽ sử dụng trừ khi bạn đang sử dụng EventEmittervì một lý do nào đó.

gulp.task('message3', function() {
  var e = new EventEmitter();
  e.on('msg', function(msg) { console.log(msg); });
  setTimeout(() => { e.emit('msg', 'HTTP Server Started'); e.emit('finish'); });
  return e;
});

4
Sau một vài giờ googling, tôi tìm thấy ví dụ này. Rất hữu ích. Cảm ơn bạn!
Paxtor

nó hữu ích cho tôi, ths!
Anan

1
Tôi rất đánh giá cao câu trả lời của bạn. +1 thời gian lớn.
Konrad Viltersten

6
Tôi đánh giá cao câu trả lời thanh lịch và nhiều thông tin của bạn vào ngày 17 tháng 11. Và hôm nay, vào ngày Giáng sinh, tôi đánh giá cao nó một lần nữa. Đây là một trong những trường hợp khi tôi ước mình có thể trao giải +2 ... Tôi không thể tin rằng goolearching không tìm ra liên kết này là top 1 khi tìm kiếm " Các nhiệm vụ sau chưa hoàn thành " hoặc " Bạn đã làm chưa quên tín hiệu hoàn thành async? "...
Konrad Viltersten

"Gói del được sử dụng thường xuyên trả về một Promise". Tôi đang sử dụng del, làm cách nào để viết mã gulp của mình để tận dụng lời hứa? (PS. Câu trả lời hoàn toàn tuyệt vời! +1)
Daniel Tonon

84

Một vấn đề với Gulp 4 .

Để giải quyết vấn đề này, hãy thử thay đổi mã hiện tại của bạn:

gulp.task('simpleTaskName', function() {
  // code...
});

ví dụ vào đây:

gulp.task('simpleTaskName', async function() {
  // code...
});

hoặc vào đây:

gulp.task('simpleTaskName', done => {
  // code...
  done();
});

2
Cuộc gọi bị mất để thực hiện là vấn đề của tôi. Cảm ơn bạn vì câu trả lời!
Marco Santarossa

1
Tuy nhiên, lưu ý rằng các hàm mũi tên không có phạm vi riêng biệt.
JepZ

19

Điều này đã làm việc!

gulp.task('script', done => {
    // ... code gulp.src( ... )
    done();
});

gulp.task('css', done => {
    // ... code gulp.src( ... )
    done();
});

gulp.task('default', gulp.parallel(
        'script',
        'css'
  )
);

2
đây là câu trả lời hay nhất
Văn dặm

13

Tôi đã gặp lỗi tương tự khi cố gắng chạy một bản dựng SASS / CSS rất đơn giản .

Giải pháp của tôi (có thể giải quyết lỗi tương tự hoặc tương tự này) chỉ đơn giản là thêm donedưới dạng tham số trong hàm tác vụ mặc định và gọi nó ở cuối tác vụ mặc định:

// Sass configuration
var gulp = require('gulp');
var sass = require('gulp-sass');

gulp.task('sass', function () {
    gulp.src('*.scss')
        .pipe(sass())
        .pipe(gulp.dest(function (f) {
            return f.base;
        }))
});

gulp.task('clean', function() {
})

gulp.task('watch', function() {
    gulp.watch('*.scss', ['sass']);
})


gulp.task('default', function(done) { // <--- Insert `done` as a parameter here...
    gulp.series('clean','sass', 'watch')
    done(); // <--- ...and call it here.
})

Hi vọng điêu nay co ich!


7
Rất vui khi thấy một ví dụ với nội dung nhiệm vụ thực tế
Jonathan

8

Bạn cần làm hai việc:

  1. Thêm asynctrước chức năng.
  2. Bắt đầu chức năng của bạn với return.

    var gulp = require('gulp');
    
    gulp.task('message', async function() {
        return console.log("HTTP Server Started");
    });

7

Tôi không thể tuyên bố là rất hiểu biết về điều này nhưng tôi đã có cùng một vấn đề và đã giải quyết nó.

Có một cách thứ 7 để giải quyết vấn đề này, bằng cách sử dụng chức năng async .

Viết chức năng của bạn nhưng thêm tiền tố async .

Bằng cách này, Gulp kết thúc chức năng trong một lời hứa và tác vụ sẽ chạy mà không gặp lỗi.

Thí dụ:

async function() {
  // do something
};

Tài nguyên:

  1. Phần cuối cùng trên trang Gulp Hoàn thành Async : Sử dụng async / await .

  2. Mozilla async có chức năng tài liệu .


7

Đây là một vấn đề khi di chuyển từ gulp phiên bản 3 đến 4, Đơn giản là bạn có thể thêm một tham số được thực hiện cho chức năng gọi lại, xem ví dụ,

   const gulp = require("gulp")

    gulp.task("message", function(done) {
      console.log("Gulp is running...")
      done()
    });

5

Giải pháp thay thế: Chúng ta cần gọi các hàm gọi lại (Tác vụ và ẩn danh):

function electronTask(callbackA)
{
    return gulp.series(myFirstTask, mySeccondTask, (callbackB) =>
    {
        callbackA();
        callbackB();
    })();    
}

2

Ở đây bạn đi: Không có nhiệm vụ đồng bộ .

Không có nhiệm vụ đồng bộ

Nhiệm vụ đồng bộ không còn được hỗ trợ. Chúng thường dẫn đến những sai lầm tinh vi khó gỡ lỗi, như quên trả lại luồng của bạn từ một nhiệm vụ.

Khi bạn thấy Did you forget to signal async completion?cảnh báo, không có kỹ thuật nào được đề cập ở trên được sử dụng. Bạn sẽ cần sử dụng cuộc gọi lại đầu tiên có lỗi hoặc trả về luồng, lời hứa, trình phát sự kiện, quy trình con hoặc có thể quan sát để giải quyết vấn đề.

Sử dụng async/await

Khi không sử dụng bất kỳ tùy chọn nào trước đó, bạn có thể xác định nhiệm vụ của mình là một nhiệm vụ async function, nó bao bọc nhiệm vụ của bạn trong một lời hứa . Điều này cho phép bạn làm việc với các lời hứa đồng bộ sử dụng awaitvà sử dụng mã đồng bộ khác.

const fs = require('fs');

async function asyncAwaitTask() {
  const { version } = fs.readFileSync('package.json');
  console.log(version);
  await Promise.resolve('some result');
}

exports.default = asyncAwaitTask;

2

Về cơ bản v3.X đơn giản hơn nhưng v4.x nghiêm ngặt trong các phương tiện của các tác vụ đồng bộ & không đồng bộ này.

Các async / chờ đợi là khá đơn giản và cách hữu ích để hiểu được công việc & vấn đề.

Sử dụng phương pháp đơn giản này

const gulp = require('gulp')

gulp.task('message',async function(){
return console.log('Gulp is running...')
})

1

Gần đây tôi đã vật lộn với điều này và tìm ra cách phù hợp để tạo ra một defaultnhiệm vụ chạy sasssau đó sass:watchlà:

gulp.task('default', gulp.series('sass', 'sass:watch'));

1

Giải pháp của tôi: đặt mọi thứ với async và chờ đợi một ngụm.

async function min_css() {
    return await gulp
        .src(cssFiles, { base: "." })
        .pipe(concat(cssOutput))
        .pipe(cssmin())
        .pipe(gulp.dest("."));
}

async function min_js() {
    return await gulp
        .src(jsFiles, { base: "." })
        .pipe(concat(jsOutput))
        .pipe(uglify())
        .pipe(gulp.dest("."));  
}

const min = async () => await gulp.series(min_css, min_js);

exports.min = min;

0

Thêm thực hiện như là một tham số trong chức năng mặc định. Điều đó sẽ làm.


0

Đối với những người đang cố gắng sử dụng gulp để triển khai cục bộ vênh vang, mã sau đây sẽ giúp

var gulp = require("gulp");
var yaml = require("js-yaml");
var path = require("path");
var fs = require("fs");

//Converts yaml to json
gulp.task("swagger", done => {
    var doc = yaml.safeLoad(fs.readFileSync(path.join(__dirname,"api/swagger/swagger.yaml")));
    fs.writeFileSync(
        path.join(__dirname,"../yourjsonfile.json"),
        JSON.stringify(doc, null, " ")
        );
    done();
});

//Watches for changes    
gulp.task('watch', function() {
  gulp.watch('api/swagger/swagger.yaml', gulp.series('swagger'));  
});

0

Đối với tôi vấn đề là khác: Angular-cli chưa được cài đặt (Tôi đã cài đặt phiên bản Node mới bằng NVM và chỉ đơn giản là quên cài đặt lại cli góc)

Bạn có thể kiểm tra chạy "phiên bản ng".

Nếu bạn không có nó, hãy chạy "npm install -g @ angular / cli"


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.