Okunabilir bir akış nasıl kapatılır (bitmeden önce)?


91

Node.js'de okunabilir bir akış nasıl kapatılır ?

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   // after closing the stream, this will not
   // be called again

   if (gotFirstLine) {
      // close this stream and continue the
      // instructions from this if
      console.log("Closed.");
   }
});

Bu şundan daha iyi olurdu:

input.on('data', function(data) {
   if (isEnded) { return; }

   if (gotFirstLine) {
      isEnded = true;
      console.log("Closed.");
   }
});

Ancak bu okuma sürecini durdurmaz ...


6
Uyarı: Bu soru yalnızca fsmodül bağlamında . closeiçinde mevcut değil Stream.Readable.
zamnuts

3
İyi haberler. Düğüm sürümü 8 stream.destroy()
şunları

readable.push(null) && readable.destroy();
Alexander Mills

Yanıtlar:


40

Çağır input.close(). Dokümanlarda yok ama

https://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L1620

işi açıkça yapıyor :) Aslında sizinkine benzer bir şey yapıyor isEnded.

DÜZENLE 2015-Nisan-19 Aşağıdaki yorumlara dayanarak ve açıklığa kavuşturmak ve güncellemek için:

  • Bu öneri bir hack'tir ve belgelenmemiştir.
  • Akım bakmak için olsa lib/fs.jshala çalışıyor> Daha sonra 1.5yrs.
  • destroy()Aramanın tercih edilebilir olmasıyla ilgili aşağıdaki yorumu kabul ediyorum .
  • Aşağıda doğru bir şekilde belirtildiği gibi, bu fs ReadStreamsgenel birReadable

Genel bir çözüme gelince: En azından dokümantasyonu anladığımdan ve hızlıca baktığımdan, bir tane varmış gibi görünmüyor _stream_readable.js.

Önerim, okunabilir akışınızı duraklatılmış moda alacak ve en azından yukarı akış veri kaynağınızda daha fazla işlem yapılmasını engelleyecektir. Dokümanlarda belirtildiği gibi, unpipe()tüm dataolay dinleyicilerini kaldırmayı ve pause()gerçekten duraklatmayı unutmayın.


1
Aslında destroyonun yerine aramayı tercih ederim . En azından autoClose'u true olarak ayarlarsanız buna denir. Kaynak koduna (bugün) bakıldığında, farklar çok azdır ( destroyaramalar close), ancak bu gelecekte değişebilir
Marcelo Diniz

Artık hatırlamıyorum, ama görünüyor :) sevmiyorum
Nitzan Shaked

4
close()Okunabilir nesne yok , çözüm yok mu? Veri değişimim her zaman eksik ...
CodeManX

Açıklığa kavuşturmak, yorumları ele almak ve genel vaka için (yoksul adamın) bir önerisini sağlamak için güncellendi. Bir jeneriği readableuygulamaya zorlamamak close()ve bunu yapmanın sınıfa özgü bir yolunu sağlamak biraz mantıklı olsa da ( fsve muhtemelen uygulayan diğer sınıflarda olduğu gibi Readable)
Nitzan Shaked

Duraklatma, yukarı akışın (gönderenin) geri basınç nedeniyle bloke olmasına veya tamponların limitlerini aşana kadar büyümesine neden olmaz mı? İdeal olarak, gönderene artık
istenmediğini söylerdik

76

Düzenleme: İyi haber! Node.js 8.0.0 ile başlamak readable.destroyresmi olarak mevcuttur: https://nodejs.org/api/stream.html#stream_readable_destroy_error

ReadStream.destroy

ReadStream.destroy işlevini istediğiniz zaman çağırabilirsiniz .

var fs = require('fs');

var readStream = fs.createReadStream('lines.txt');
readStream
    .on('data', function (chunk) {
        console.log(chunk);
        readStream.destroy();
    })
    .on('end', function () {
        // This may not been called since we are destroying the stream
        // the first time 'data' event is received
        console.log('All the data in the file has been read');
    })
    .on('close', function (err) {
        console.log('Stream has been destroyed and file has been closed');
    });

Genel işlev ReadStream.destroybelgelenmemiştir (Node.js v0.12.2) ancak GitHub'da kaynak koduna göz atabilirsiniz ( 5 Ekim 2012 commit ).

destroyFonksiyon içten işaretlemek ReadStreamtahrip ve deyişiyle örneğini closedosyasını serbest bırakmak için işlevini.

Dosyanın tam olarak ne zaman kapatıldığını bilmek için close olayını dinleyebilirsiniz . Son olay verisi tamamen tüketildiği sürece patlamaz.


Not destroy(ve close) işlevleri özeldir fs.ReadStream . Genel stream.readable "arabiriminin" bir parçası yoktur.


En azından Node'un en son sürümünde (diğerlerini kontrol etmedim), dosya tanımlayıcı otomatik olarak kapatılır . Bununla birlikte, akışın errorhiç okunmazsa sonunda ateşlenmesini sağlamak için herhangi bir kapsamlı test yapmadım. Bunun dışında, endişeleneceğim diğer tek sızıntı olay işleyicilerdir - yine, bundan% 100 emin değilim, ancak 2010'da Isaacs'ın müjdesi, işleyicilerin yayıcılar gc'd olduğunda budanır: groups.google.com/d/msg/nodejs/pXbJVo0NtaY/BxUmF_jp9LkJ
mikermcneil

1
Veriler çok küçükse, on('data') yalnızca bir kez tetiklenir, yani hiç tetiklenmez .close(), sadece başkasına hatırlatın.
bitfishxyz


12

Yapamazsın. Düğüm 5.3.0'dan itibaren genel Okunabilir bir akışı kapatmanın / kapatmanın / durdurmanın / yok etmenin belgelenmiş bir yolu yoktur . Bu, Düğüm akışı mimarisinin bir sınırlamasıdır.

Buradaki diğer yanıtların açıkladığı gibi, fs.ReadStream gibi Node tarafından sağlanan Okunabilir özel uygulamalar için belgelenmemiş hackler vardır . Bunlar, herhangi bir Okunabilir için genel çözümler değildir.

Biri burada yanıldığımı kanıtlayabilirse, lütfen yapın. İmkansız olduğunu söylediğim şeyi yapabilmeyi isterim ve düzeltilmekten memnuniyet duyarım.

DÜZENLEME : İşte benim çözümüm: karmaşık bir dizi çağrı olsa da ardışık düzenim için uygulayın . .destroy()unpipe()Ve tüm bu karmaşıklıktan sonra , her durumda düzgün çalışmıyor .

DÜZENLEME : Düğüm v8.0.0 destroy(), Okunabilir akışlar için bir API ekledi .


1
Artık stream.pipeline, "yönlendirme hatalarını ele aldığını ve düzgün bir şekilde temizlendiğini ve ardışık düzen tamamlandığında bir geri arama sağladığını" iddia eden var. Bu yardımcı olur mu?
andrewdotn

11

Versiyonda 4.*.*, akışa boş bir değer girmek bir EOFsinyali tetikleyecektir .

Gönderen nodejs docs

Null dışında bir değer iletilirse, push () yöntemi sonraki akış işlemcilerinin tüketmesi için kuyruğa bir yığın veri ekler. Null geçirilirse, akışın sonunu (EOF) işaret eder, bundan sonra daha fazla veri yazılamaz.

Bu, bu sayfadaki diğer birçok seçeneği denedikten sonra benim için çalıştı.


1
Benim için çalışıyor. Ancak, beklenen davranışı - yani tüm akışın durmasını sağlamak için null'a bastıktan sonra done () geri çağrısını çağırmaktan kaçınmam gerekti.
Zengin Apodaca

6

Bu yok etme modülü, bir akışın farklı API'leri ve Node.js hatalarını ele alarak yok edilmesini sağlamak içindir. Şu an en iyi seçeneklerden biri.

NB. Düğüm 10'dan, .destroyyöntemi daha fazla bağımlılık olmadan kullanabilirsiniz .


3

yourstream.resume()İle akışı temizleyip kapatabilirsiniz; bu, akıştaki her şeyi atar ve sonunda kapatır.

Gönderen resmi dokümanlar :

readable.resume ():

Dönüş: bu

Bu yöntem, okunabilir akışın 'veri' olaylarını yaymaya devam etmesine neden olacaktır.

Bu yöntem, akışı akış moduna geçirecektir. Bir akıştan gelen verileri tüketmek istemiyorsanız, ancak 'son' olayına ulaşmak istiyorsanız, veri akışını açmak için stream.resume () işlevini çağırabilirsiniz.

var readable = getReadableStreamSomehow();
readable.resume();
readable.on('end', () => {
  console.log('got to the end, but did not read anything');
});

Bu, akışı "boşaltmak" olarak adlandırılabilir. Bizim durumumuzda, elbette bir 'data'olay dinleyicimiz vardı , ancak bir booleanı kontrol ettirdik, if (!ignoring) { ... }böylece akışı boşaltırken verileri işlemeyecek. ignoring = true; readable.resume();
joeytwiddle

5
Elbette bu, akışın 'end'bir noktada olacağını varsayar . Tüm yayınlar bunu yapmaz! (Örneğin tarihi sonsuza kadar her saniye gönderen bir akış.)
joeytwiddle

3

Bu eski bir soru ama ben de cevabı arıyordum ve uygulamam için en iyisini buldum. Hem endve closebu en temiz çözüm olduğunu düşünüyorum bu yüzden olaylar yayılan olsun.

Bu, 4.4. * Düğümündeki hile yapacak (yazım sırasındaki kararlı sürüm):

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   if (gotFirstLine) {
      this.end(); // Simple isn't it?
      console.log("Closed.");
   }
});

Çok ayrıntılı bir açıklama için bkz: http://www.bennadel.com/blog/2692-you-have-to-explicitly-end-streams-after-pipes-break-in-node-js.htm


2

Buradaki kod hile güzel bir şekilde işleyecek:

function closeReadStream(stream) {
    if (!stream) return;
    if (stream.close) stream.close();
    else if (stream.destroy) stream.destroy();
}

writeStream.end (), writeStream'i kapatmanın en iyi yoludur ...


1
Neden .end () 'den bahsediyorsunuz, ama o zaman kodunuz close ve destroy kullanıyor ve end bile kullanmıyor?
Lucas B

1
örnekte bir okuma akışını kapatıyorum ... a writeStream - use.end
g00dnatur3
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.