ข้อผิดพลาดอึก: งานต่อไปนี้ไม่เสร็จสมบูรณ์: คุณลืมที่จะส่งสัญญาณให้เสร็จสิ้น async?


211

ฉันมีgulpfile.jsต่อไปนี้ซึ่งฉันกำลังดำเนินการผ่านข้อความบรรทัดคำสั่งgulp :

var gulp = require('gulp');

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

ฉันได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้:

[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?

ฉันใช้อึก 4 ในระบบ Windows 10 นี่คือผลลัพธ์จากgulp --version:

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

1
webpack-streamถ้าคุณอยู่ที่นี่เพราะคุณได้มีปัญหากับ ใช้สิ่งนี้: github.com/shama/webpack-stream/issues/…
B3none

คำตอบ:


448

เนื่องจากงานของคุณอาจมีรหัสไม่ตรงกันคุณต้องส่งสัญญาณอึกเมื่องานของคุณเสร็จสิ้นการดำเนินการ (= "async complete")

ใน Gulp 3.x คุณสามารถหนีโดยไม่ทำสิ่งนี้ หากคุณไม่ได้ส่งสัญญาณการเสร็จสิ้น async อย่างชัดเจนเพียงแค่คิดว่างานของคุณซิงโครนัสและจะเสร็จสิ้นทันทีที่ฟังก์ชันงานของคุณส่งคืน อึก 4.x เข้มงวดในเรื่องนี้ คุณต้องส่งสัญญาณความสำเร็จของงานอย่างชัดเจน

คุณสามารถทำได้หกวิธี :

1. ส่งคืนสตรีม

นี่ไม่ใช่ตัวเลือกหากคุณพยายามพิมพ์บางอย่างเท่านั้น แต่อาจเป็นกลไกการทำให้เสร็จสมบูรณ์ที่ใช้บ่อยที่สุดเนื่องจากคุณมักจะทำงานกับลำธารอึก นี่คือตัวอย่าง (มีการวางแผนค่อนข้าง) แสดงให้เห็นถึงกรณีการใช้งานของคุณ:

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

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

ส่วนสำคัญที่นี่คือreturnคำสั่ง หากคุณไม่ได้ส่งกระแสข้อมูลอีกต่อไปอึกไม่สามารถระบุได้ว่ากระแสข้อมูลเสร็จสิ้นแล้ว

2. ส่งคืน Promise

นี่เป็นกลไกที่เหมาะสมกว่าสำหรับกรณีการใช้งานของคุณ โปรดทราบว่าส่วนใหญ่คุณจะไม่ต้องสร้างPromiseวัตถุด้วยตัวเองโดยปกติจะให้บริการโดยแพคเกจ (เช่นdelแพคเกจที่ใช้บ่อยส่งคืน a Promise)

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

การใช้ไวยากรณ์async / awaitนี้สามารถทำให้ง่ายยิ่งขึ้นอีก ฟังก์ชั่นทั้งหมดที่ทำเครื่องหมายasyncส่งคืนสัญญาโดยปริยายดังนั้นการทำงานต่อไปนี้ก็เช่นกัน (หากรุ่น node.jsของคุณรองรับ ):

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

3. เรียกฟังก์ชั่นการโทรกลับ

นี่อาจเป็นวิธีที่ง่ายที่สุดสำหรับกรณีการใช้งานของคุณ: gulp ส่งผ่านฟังก์ชันการเรียกกลับไปที่งานของคุณโดยอัตโนมัติเป็นอาร์กิวเมนต์แรก เพียงเรียกใช้ฟังก์ชันนั้นเมื่อเสร็จสิ้น:

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

4. ส่งคืนกระบวนการลูก

สิ่งนี้มีประโยชน์เป็นส่วนใหญ่หากคุณต้องเรียกใช้เครื่องมือบรรทัดคำสั่งโดยตรงเนื่องจากไม่มีตัวห่อหุ้ม node.js มันใช้งานได้กับกรณีการใช้งานของคุณ แต่เห็นได้ชัดว่าฉันจะไม่แนะนำ (โดยเฉพาะอย่างยิ่งเนื่องจากมันไม่ได้พกพามาก):

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

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

5. กลับRxJSObservable

ฉันไม่เคยใช้กลไกนี้ แต่ถ้าคุณใช้ RxJS มันอาจมีประโยชน์ มันช่างเกินกำลังหากคุณต้องการพิมพ์บางอย่าง:

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. ส่งคืน EventEmitter

เช่นเดียวกับก่อนหน้านี้ฉันกำลังรวมสิ่งนี้ไว้ด้วยเพื่อความสมบูรณ์ แต่มันไม่ใช่สิ่งที่คุณจะใช้เว้นแต่คุณจะใช้EventEmitterด้วยเหตุผลบางอย่าง

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
หลังจาก googling สองสามชั่วโมงฉันพบตัวอย่างนี้ มีประโยชน์มาก ขอบคุณ!
paxtor

มันมีประโยชน์สำหรับฉันแล้ว!
Anan

1
ฉันขอขอบคุณคำตอบของคุณ +1 ครั้งใหญ่
Konrad Viltersten

6
ฉันชื่นชมคำตอบที่หรูหราและให้ข้อมูลของคุณในวันที่ 17 พฤศจิกายน และวันนี้ในวันคริสต์มาสฉันชื่นชมมันอีกครั้ง นี่เป็นหนึ่งในกรณีที่ฉันหวังว่าฉันจะได้รับรางวัล +2 ... ฉันไม่อยากจะเชื่อเลยว่า goolearching ไม่ได้ทำลิงค์นี้เป็นอันดับ 1 เมื่อค้นหา " งานต่อไปนี้ไม่เสร็จ " หรือ " คุณไม่ ลืมที่จะส่งสัญญาณการซิงค์แบบสมบูรณ์หรือไม่ "...
Konrad Viltersten

"แพคเกจเดลที่ใช้บ่อยส่งคืนสัญญา" ฉันใช้เดลฉันจะเขียนรหัส gulp ของฉันเพื่อใช้ประโยชน์จากสัญญาได้อย่างไร (PS. คำตอบที่น่าอัศจรรย์อย่างยิ่ง! +1)
Daniel Tonon

84

มีปัญหากับอึก 4

สำหรับการแก้ปัญหานี้ให้ลองเปลี่ยนรหัสปัจจุบันของคุณ:

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

ตัวอย่างเช่นนี้:

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

หรือเป็นสิ่งนี้:

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

2
ปัญหาการโทรที่ขาดหายไปเป็นปัญหาของฉัน ขอบคุณสำหรับคำตอบ!
Marco Santarossa

1
อย่างไรก็ตามโปรดทราบว่าฟังก์ชั่นลูกศรไม่มีขอบเขตแยกต่างหาก
JepZ


13

ฉันได้รับข้อผิดพลาดเดียวกันนี้พยายามรันSASS / CSS build ที่ง่ายมาก

วิธีแก้ปัญหาของฉัน (ซึ่งอาจแก้ไขข้อผิดพลาดที่เหมือนกันหรือคล้ายกันนี้) เป็นเพียงการเพิ่มdoneเป็นพารามิเตอร์ในฟังก์ชั่นงานเริ่มต้นและจะเรียกมันในตอนท้ายของงานเริ่มต้น:

// 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.
})

หวังว่านี่จะช่วยได้!


7
ยินดีที่ได้เห็นตัวอย่างที่มีเนื้อหางานจริง
Jonathan

8

คุณต้องทำสองสิ่ง:

  1. เพิ่มasyncก่อนฟังก์ชั่น
  2. returnเริ่มต้นการทำงานของคุณด้วย

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

7

ฉันไม่สามารถอ้างว่ามีความรู้ในเรื่องนี้มาก แต่ฉันมีปัญหาเดียวกันและแก้ไขได้

มีวิธีที่ 7 เพื่อแก้ไขปัญหานี้โดยใช้เป็นฟังก์ชั่น async

เขียนฟังก์ชั่นของคุณ แต่เพิ่มคำนำหน้าasync

ด้วยการทำสิ่งนี้ Gulp จะหุ้มฟังก์ชั่นตามสัญญาและงานจะทำงานโดยไม่มีข้อผิดพลาด

ตัวอย่าง:

async function() {
  // do something
};

แหล่งข้อมูล:

  1. ส่วนสุดท้ายในอึกหน้าAsync เสร็จ : ใช้ async

  2. Mozillaเอกสารฟังก์ชั่น async


7

นี่เป็นปัญหาเมื่อทำการโยกย้ายจาก gulp เวอร์ชัน 3 ถึง 4 เพียงแค่คุณสามารถเพิ่มพารามิเตอร์ที่ทำลงในฟังก์ชั่นโทรกลับได้โปรดดูตัวอย่าง

   const gulp = require("gulp")

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

5

วิธีแก้ปัญหา: เราจำเป็นต้องเรียกใช้ฟังก์ชันการโทรกลับ (Task และ Anonymous):

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

2

ไปเลย: ไม่ต้องทำงานแบบซิงโครนั

ไม่มีงานแบบซิงโครนัส

ไม่สนับสนุนงานซิงโครนัสอีกต่อไป พวกเขามักจะนำไปสู่ข้อผิดพลาดเล็กน้อยที่ยากต่อการแก้ไขเช่นลืมที่จะคืนค่ากระแสข้อมูลของคุณจากงาน

เมื่อคุณเห็นDid you forget to signal async completion?คำเตือนจะไม่มีการใช้เทคนิคดังกล่าวข้างต้น คุณจะต้องใช้การโทรกลับข้อผิดพลาดครั้งแรกหรือส่งคืนสตรีมสัญญาเหตุการณ์อีซีแอลกระบวนการเด็กหรือที่สังเกตได้เพื่อแก้ไขปัญหา

ใช้async/await

เมื่อไม่ได้ใช้ตัวเลือกใด ๆ ก่อนหน้านี้คุณสามารถกำหนดงานของคุณเป็นasync functionที่ wraps งานของคุณในสัญญา สิ่งนี้จะช่วยให้คุณสามารถทำงานกับสัญญาที่ใช้awaitพร้อมกันและใช้รหัสซิงโครนัสอื่น ๆ

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

โดยทั่วไปแล้ว v3.X นั้นเรียบง่ายกว่า แต่ v4.x เข้มงวดในการใช้งานแบบซิงโครนัสและแบบอะซิงโครนัส

async / รอคอยสวยเรียบง่ายและวิธีที่เป็นประโยชน์ในการทำความเข้าใจขั้นตอนการทำงานและปัญหา

ใช้วิธีการง่าย ๆ นี้

const gulp = require('gulp')

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

1

ฉันกำลังดิ้นรนกับเรื่องนี้เมื่อเร็ว ๆ นี้และพบวิธีที่เหมาะสมในการสร้างdefaultงานที่ทำงานsassแล้วsass:watchคือ:

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

1

วิธีการแก้ปัญหาของฉัน: ใส่ทุกอย่างด้วย async และรออึก

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

เพิ่มเสร็จเป็นพารามิเตอร์ในฟังก์ชั่นเริ่มต้น ที่จะทำ


0

สำหรับผู้ที่พยายามใช้อึกสำหรับการนำไปใช้งานแบบโลคัลรหัสต่อไปนี้จะช่วยได้

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

สำหรับฉันปัญหาแตกต่างกัน: ไม่ได้ติดตั้ง Angular-cli (ฉันติดตั้งโหนดรุ่นใหม่โดยใช้ NVM และเพียงลืมติดตั้ง cli เชิงมุมใหม่)

คุณสามารถตรวจสอบการทำงาน "รุ่น ng"

หากคุณไม่มีให้เรียกใช้ "npm install -g @ angular / cli"


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.