JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 24
  • Score
    100M100P100Q58378F
  • License MIT

Handle completion and errors with elegance! Support for streams, callbacks, promises, child processes, async/await and sync functions. A drop-in replacement for [async-done][] - pass 100% of its tests plus more

Package Exports

  • always-done

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (always-done) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

always-done npmjs.com The MIT License npm downloads

Handle completion and errors with elegance! Support for streams, callbacks, promises, child processes, async/await and sync functions. A drop-in replacement for async-done - pass 100% of its tests plus more

code climate standard code style travis build status coverage status dependency status

Table of Contents

Install

Install with npm

$ npm i always-done --save

Usage

For more use-cases see the tests

const alwaysDone = require('always-done')

API

alwaysDone

Handle completion of fn and optionally pass done callback, otherwise it returns a thunk. If that thunk does not accept function, it returns another thunk until you pass done to it.

Params

  • <fn> {Function}: function to be called
  • [done] {Function}: on completion
  • returns {Function}: thunk until you pass done to that thunk

Example

var alwaysDone = require('always-done')

alwaysDone(function (cb) {
  cb(null, 123)
}, function done (err, res) {
  console.log(err, res) // => null, 123
})

alwaysDone(function (cb) {
  cb(new Error('foo bar'))
}, function done (err) {
  console.log(err) // => Error: foo bar
})

Background

Behind the scenes we use just good plain old try/catch block. Sounds you strange? See what "hard" job is done on try-catch-callback and try-catch-core.

In the first one, we just calls a function inside try/catch and calls done callback with error or result of that function.

About second one, there we wraps the done callback with once and dezalgo to ensure it will be called in the next tick.

Here, in always-done, we just give a callback to that try-catch-core package and "listen" what are the result. Actually we not listening anything, we just make a few checks to understand what the incoming value is - promise, child process, stream, observable and etc.

Resolution

Nothing so magical. Try/catch block for most of the things works briliant. And on-stream-end module (which is drop-in replacement for end-of-stream) for streams and child processes.

Support

async/await completion

alwaysDone(async function () {
  return await Promise.resolve('foobar')
}, function done (e, res) {
  console.log(res) // => 'foobar'
})

back to top

Callbacks completion

var alwaysDone = require('always-done')

alwaysDone(function (cb) {
  fs.readFile('./package.json', 'utf8', cb)
}, function done (err, res) {
  if (err) return console.log(err)
 
  var pkg = JSON.parse(res)
  console.log(pkg.name) // => 'always-done'
})

back to top

Synchronous functions

Returning a value

alwaysDone(function () {
  return 123
}, function done (e, res) {
  console.log(res) // => 123
})

Returning an error

alwaysDone(function () {
  return new Error('qux bar')
}, function done (err) {
  console.log(err.message) // => 'qux bar'
})

back to top

Promises

Returning a resolved Promise

alwaysDone(function () {
  return Promise.resolve(12345)
}, function done (e, res) {
  console.log(res) // => 12345
})

Returning a rejected Promise

alwaysDone(function () {
  return Promise.reject(new Error('foo bar'))
}, function done (err) {
  console.log(err.message) // => 'foo bar
})

back to top

Streams

Unpiped streams

alwaysDone(function () {
  return fs.createReadStream('./package.json')
}, function done (e) {
  console.log('stream completed')
})

Failing unpiped streams

alwaysDone(function () {
  return fs.createReadStream('foo bar')
}, function done (err) {
  console.log(err.code) // => ENOENT
  console.log(err.message) // => No such file or directory
})

Failing piped streams

alwaysDone(function () {
  var read = fs.createReadStream('foo bar')
  return read.pipe(through2())
}, function done (err) {
  console.log(err.code) // => ENOENT
  console.log(err.message) // => No such file or directory
})

back to top

Observables

Empty observable

var Observable = require('rx').Observable

alwaysDone(function () {
  return Observable.empty()
}, function done (e, res) {
  console.log(e, res) // => null, undefined
})

Successful observable

alwaysDone(function () {
  return Observable.return([1, 2, 3])
}, function done (e, res) {
  console.log(res) // => [1, 2, 3]
})

Failing observable

alwaysDone(function () {
  return Observable.throw(new Error('observable error'))
}, function done (err) {
  console.log(err.message) // => 'observable error'
})

back to top

Child Process

Successful exec

var cp = require('child_process')

alwaysDone(function () {
  return cp.exec('echo hello world')
}, function done (e, res) {
  console.log(res) // => 'hello world'
})

Failing exec

var cp = require('child_process')

alwaysDone(function () {
  return cp.exec('foo-bar-baz sasa')
}, function done (err) {
  console.log(err.message) // => 'exited with error code: 12'
})

Failing spawn

var cp = require('child_process')

alwaysDone(function () {
  return cp.spawn('foo-bar-baz', ['hello world'])
}, function done (err) {
  console.log(err.code) // => ENOENT
})

back to top

Handling native errors

alwaysDone(function () {
  foo
  return 55
}, function (err) {
  console.log(err.name)
  // => ReferenceError: foo is not defined
})

back to top

Always completes

It may looks strange, but it's logical.

Example

// passing empty function
alwaysDone(function () {}, function (err, res) {
  console.log(err, res) // => null, undefined
})

Contributing

Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.
But before doing anything, please read the CONTRIBUTING.md guidelines.

Charlike Make Reagent new message to charlike freenode #charlike

tunnckoCore.tk keybase tunnckoCore tunnckoCore npm tunnckoCore twitter tunnckoCore github