gọi lại để xử lý hoàn thành đường ống


196

Tôi đang sử dụng mã node.js sau để tải xuống tài liệu từ một số url và lưu nó vào đĩa. Tôi muốn được thông báo về thời điểm tài liệu được tải xuống. Tôi chưa thấy bất kỳ cuộc gọi lại nào với pipe. Hoặc, Có sự kiện 'kết thúc' nào có thể được ghi lại khi hoàn tất tải xuống không?

request(some_url_doc).pipe(fs.createWriteStream('xyz.doc'));

Câu trả lời:


302

Các luồng là EventEmitters để bạn có thể nghe một số sự kiện. Như bạn đã nói có một finishsự kiện cho yêu cầu (trước đây end).

 var stream = request(...).pipe(...);
 stream.on('finish', function () { ... });

Để biết thêm thông tin về những sự kiện có sẵn, bạn có thể kiểm tra trang tài liệu truyền phát .


12
var r = request(...).on("end",function(){/* CALLBACK */}).pipe(...);
Denys Vitali

6
đối với tôi sự kiện 'đóng', thay vì 'kết thúc' hoạt độngr.on('close'), function () {...})
Judson

9
Sự kiện 'kết thúc' bây giờ là 'kết thúc' Sự kiện ống: nodejs.org/api/stream.html#stream_event_finish
Cầu tàu-Luc Gendreau

13
Sự kiện 'kết thúc' vẫn tồn tại và được sử dụng trên các luồng có thể đọc được. Luồng có thể ghi được sử dụng 'kết thúc'. Điều này là do luồng Biến đổi là sự pha trộn của cả hai và cần phân biệt giữa các sự kiện.
gật đầu

16
Chủ đề này là một bản tóm tắt tốt về cách làm việc với các luồng nút trông như thế nào.
pomber

43

Tài liệu nodejs dựa trên, http://nodejs.org/api/stream.html#stream_event_finish , nó sẽ xử lý finishsự kiện của writableStream .

var writable = getWriteable();
var readable = getReadable();
readable.pipe(writable);
writable.on('finish', function(){ ... });

Câu trả lời được chấp nhận không hoạt động với tôi với nút v0.12.7, nhưng giải pháp của bạn thì có.
Luca Steeb

9

Đoạn mã cho nội dung đường ống từ web thông qua http (s) đến hệ thống tập tin. Như @starbeamrainbowlabs nhận thấy sự kiện finishkhông hoạt động

var tmpFile = "/tmp/somefilename.doc";

var ws = fs.createWriteStream(tmpFile);
ws.on('finish', function() {
  // pipe done here, do something with file
});

var client = url.slice(0, 5) === 'https' ? https : http;
client.get(url, function(response) {
  return response.pipe(ws);
});

'Kết thúc' hoạt động với tôi và 'kết thúc' thì không. Cảm ơn bạn!
shaosh

1
trong một trường hợp cụ thể, kết thúc dường như được kích hoạt trước khi tất cả các byte dự kiến ​​đến
Michael

4

Tôi tìm thấy một giải pháp khác một chút về vấn đề của tôi liên quan đến bối cảnh này. Suy nghĩ đáng chia sẻ.

Hầu hết các ví dụ tạo readStreamstừ tập tin. Nhưng trong trường hợp của tôi readStreamphải được tạo từ JSONchuỗi đến từ một nhóm thông báo.

var jsonStream = through2.obj(function(chunk, encoding, callback) {
                    this.push(JSON.stringify(chunk, null, 4) + '\n');
                    callback();
                });
// message.value --> value/text to write in write.txt 
jsonStream.write(JSON.parse(message.value));
var writeStream = sftp.createWriteStream("/path/to/write/write.txt");

//"close" event didn't work for me!
writeStream.on( 'close', function () {
    console.log( "- done!" );
    sftp.end();
    }
);

//"finish" event didn't work for me either!
writeStream.on( 'close', function () {
    console.log( "- done!"
        sftp.end();
        }
);

// finally this worked for me!
jsonStream.on('data', function(data) {
    var toString = Object.prototype.toString.call(data);
    console.log('type of data:', toString);
    console.log( "- file transferred" );
});

jsonStream.pipe( writeStream );

Thay vì nghe "kết thúc", bạn có hai trình xử lý cho "đóng", có lẽ đó là lý do. Sự kiện "kết thúc" làm việc cho tôi.
jowo

3

Đây là một giải pháp xử lý lỗi trong các yêu cầu và gọi lại sau khi tệp được viết:

request(opts)
    .on('error', function(err){ return callback(err)})
    .pipe(fs.createWriteStream(filename))
    .on('finish', function (err) {
        return callback(err);
    });
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.