« index

Coverage for /Users/kris/q-io/writer.js : 85%

90 lines | 77 run | 13 missing | 1 partial | 12 blocks | 4 blocks run | 8 blocks missing

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

  var Q = require("q");
  
  /**
   * Wraps a Node writable stream, providing an API similar to
   * Narwhal's synchronous `io` streams, except returning and
   * accepting promises for long-latency operations.
   *
   * @param stream any Node writable stream
   * @returns {Promise * Writer} a promise for the
   * text writer.
   */
  module.exports = Writer;
  function Writer(_stream, charset) {
      var self = Object.create(Writer.prototype);
  
      if (charset && _stream.setEncoding) // TODO complain about inconsistency
          _stream.setEncoding(charset);
  
      var begin = Q.defer();
      var drained = Q.defer();
  
      _stream.on("error", function (reason) {
          begin.reject(reason);
      });
  
      _stream.on("drain", function () {
          begin.resolve(self);
          drained.resolve();
          drained = Q.defer();
      });
  
      /***
       * Writes content to the stream.
       * @param {String} content
       * @returns {Promise * Undefined} a promise that will
       * be resolved when the buffer is empty, meaning
       * that all of the content has been sent.
       */
      self.write = function (content) {
          if (!_stream.writeable && !_stream.writable)
              return Q.reject(new Error("Can't write to non-writable (possibly closed) stream"));
          if (_stream.encoding == "binary" && !(content instanceof Buffer)) {
              content = new Buffer(content);
          }
          if (!_stream.write(content)) {
              return drained.promise;
          } else {
              return Q.resolve();
          }
      };
  
      /***
       * Waits for all data to flush on the stream.
       *
       * @returns {Promise * Undefined} a promise that will
       * be resolved when the buffer is empty
       */
      self.flush = function () {
          return drained.promise;
      };
  
      /***
       * Closes the stream, waiting for the internal buffer
       * to flush.
       *
       * @returns {Promise * Undefined} a promise that will
       * be resolved when the stream has finished writing,
       * flushing, and closed.
       */
      self.close = function () {
          _stream.end();
          drained.resolve(); // we will get no further drain events
          return Q.resolve(); // closing not explicitly observable
      };
  
      /***
       * Terminates writing on a stream, closing before
       * the internal buffer drains.
       *
       * @returns {Promise * Undefined} a promise that will
       * be resolved when the stream has finished closing.
       */
      self.destroy = function () {
          _stream.destroy();
          drained.resolve(); // we will get no further drain events
          return Q.resolve(); // destruction not explicitly observable
      };
  
      return Q.resolve(self); // todo returns the begin.promise
  }
« index | cover.io