diff --git a/docs/src/pages/docs/crocks/Async.md b/docs/src/pages/docs/crocks/Async.md
index 3a9173bd7..9606b7e39 100644
--- a/docs/src/pages/docs/crocks/Async.md
+++ b/docs/src/pages/docs/crocks/Async.md
@@ -379,8 +379,17 @@ As such, the need for binding may arise. `fromNode` provides a second, optional
argument that takes the context that will be used to bind the function being
wrapped.
-Any curried interface will not be respected and if a curried interface is needed
-then [`nAry`][nary] can be used.
+The function returned from `fromNode` will be automatically curried, allowing you
+to partially apply the function up to its penultimate parameter[1], so long as the
+arity of the original function given to `fromNode` can be determined via its `.length` property.
+
+In practice this means that functions defined via `compose` or those making use
+of `arguments`, spread args (`...args`) or default values for parameters, will not be
+good candidates for partial application.
+
+[1] The final parameter to the incoming function is provided to you by`fromNode` rather
+than being part of the parameters that can be partially applied.
+
diff --git a/src/Async/Async.spec.js b/src/Async/Async.spec.js
index 4f963472f..8830622dd 100644
--- a/src/Async/Async.spec.js
+++ b/src/Async/Async.spec.js
@@ -225,6 +225,21 @@ test('Async fromNode resolution', t => {
Async.fromNode(resCPS)(val).fork(rej(val), res(val))
})
+test('Async fromNode partially applied', t => {
+ t.plan(2)
+
+ const val = 'super fun'
+
+ const rejCPS = (x, y, cf) => cf(x, y)
+ const resCPS = (x, y, cf) => cf(null, x, y)
+
+ const rej = y => x => t.equal(x, y, 'rejects an erred CPS')
+ const res = y => x => t.equal(x, y, 'resolves a good CPS')
+
+ Async.fromNode(rejCPS)(val)(val).fork(rej(val), res(val))
+ Async.fromNode(resCPS)(val)(val).fork(rej(val), res(val))
+})
+
test('Async all', t => {
const all = bindFunc(Async.all)
diff --git a/src/Async/index.js b/src/Async/index.js
index d902de6d4..f72bd2a04 100644
--- a/src/Async/index.js
+++ b/src/Async/index.js
@@ -48,14 +48,22 @@ function fromNode(fn, ctx) {
throw new TypeError('Async.fromNode: CPS function required')
}
- return (...args) =>
- Async((reject, resolve) => {
+ const _fn = curry(fn)
+
+ return (...args) => {
+
+ if (args.length < _fn.length - 1) {
+ return fromNode(_fn(...args), ctx)
+ }
+
+ return Async((reject, resolve) => {
fn.apply(ctx,
args.concat(
(err, data) => err ? reject(err) : resolve(data)
)
)
})
+ }
}
function fromPromise(fn) {