Dieses Repository beinhaltet HTML- und Javascript Code zur einer NotizenWebApp auf Basis von Web Storage. Zudem sind Mocha/Chai Tests im Browser enthalten. https://meinenotizen.netlify.app/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. //filter will reemit the data if cb(err,pass) pass is truthy
  2. // reduce is more tricky
  3. // maybe we want to group the reductions or emit progress updates occasionally
  4. // the most basic reduce just emits one 'data' event after it has recieved 'end'
  5. var Stream = require('stream').Stream
  6. //create an event stream and apply function to each .write
  7. //emitting each response as data
  8. //unless it's an empty callback
  9. module.exports = function (mapper, opts) {
  10. var stream = new Stream()
  11. , self = this
  12. , inputs = 0
  13. , outputs = 0
  14. , ended = false
  15. , paused = false
  16. , destroyed = false
  17. , lastWritten = 0
  18. , inNext = false
  19. this.opts = opts || {};
  20. var errorEventName = this.opts.failures ? 'failure' : 'error';
  21. // Items that are not ready to be written yet (because they would come out of
  22. // order) get stuck in a queue for later.
  23. var writeQueue = {}
  24. stream.writable = true
  25. stream.readable = true
  26. function queueData (data, number) {
  27. var nextToWrite = lastWritten + 1
  28. if (number === nextToWrite) {
  29. // If it's next, and its not undefined write it
  30. if (data !== undefined) {
  31. stream.emit.apply(stream, ['data', data])
  32. }
  33. lastWritten ++
  34. nextToWrite ++
  35. } else {
  36. // Otherwise queue it for later.
  37. writeQueue[number] = data
  38. }
  39. // If the next value is in the queue, write it
  40. if (writeQueue.hasOwnProperty(nextToWrite)) {
  41. var dataToWrite = writeQueue[nextToWrite]
  42. delete writeQueue[nextToWrite]
  43. return queueData(dataToWrite, nextToWrite)
  44. }
  45. outputs ++
  46. if(inputs === outputs) {
  47. if(paused) paused = false, stream.emit('drain') //written all the incoming events
  48. if(ended) end()
  49. }
  50. }
  51. function next (err, data, number) {
  52. if(destroyed) return
  53. inNext = true
  54. if (!err || self.opts.failures) {
  55. queueData(data, number)
  56. }
  57. if (err) {
  58. stream.emit.apply(stream, [ errorEventName, err ]);
  59. }
  60. inNext = false;
  61. }
  62. // Wrap the mapper function by calling its callback with the order number of
  63. // the item in the stream.
  64. function wrappedMapper (input, number, callback) {
  65. return mapper.call(null, input, function(err, data){
  66. callback(err, data, number)
  67. })
  68. }
  69. stream.write = function (data) {
  70. if(ended) throw new Error('map stream is not writable')
  71. inNext = false
  72. inputs ++
  73. try {
  74. //catch sync errors and handle them like async errors
  75. var written = wrappedMapper(data, inputs, next)
  76. paused = (written === false)
  77. return !paused
  78. } catch (err) {
  79. //if the callback has been called syncronously, and the error
  80. //has occured in an listener, throw it again.
  81. if(inNext)
  82. throw err
  83. next(err)
  84. return !paused
  85. }
  86. }
  87. function end (data) {
  88. //if end was called with args, write it,
  89. ended = true //write will emit 'end' if ended is true
  90. stream.writable = false
  91. if(data !== undefined) {
  92. return queueData(data, inputs)
  93. } else if (inputs == outputs) { //wait for processing
  94. stream.readable = false, stream.emit('end'), stream.destroy()
  95. }
  96. }
  97. stream.end = function (data) {
  98. if(ended) return
  99. end()
  100. }
  101. stream.destroy = function () {
  102. ended = destroyed = true
  103. stream.writable = stream.readable = paused = false
  104. process.nextTick(function () {
  105. stream.emit('close')
  106. })
  107. }
  108. stream.pause = function () {
  109. paused = true
  110. }
  111. stream.resume = function () {
  112. paused = false
  113. }
  114. return stream
  115. }