promisify
Version:
Convert callback-based APIs to promises
151 lines (128 loc) • 4.5 kB
JavaScript
var when = require('when');
var PStream = require('./pstream');
function identity(x) {
return x;
}
// Append items to an array-like object
function append(arrlike /* , items... */) {
return Array.prototype.slice.call(arrlike, 0).concat(Array.prototype.slice.call(arguments, 1));
}
// Produces a transformer that takes a value and simply returns it.
function promisify_value(result_transformer) {
result_transformer = result_transformer || identity;
var transformer = function (promise) {
result_transformer(promise);
};
transformer.for_property = function (obj_promise, prop) {
return when(obj_promise, function (obj) {
result_transformer(obj[prop]);
});
};
return transformer;
}
// Produces a transformer that takes a promised function, and returns
// a function returning a promise, optionally transforming that
// promise.
function promisify_func(result_transformer) {
result_transformer = result_transformer || identity;
var transformer = function (func_promise) {
return function (/* ... */) {
var args = arguments;
return result_transformer(when(func_promise, function (func) {
return func.apply(null, args);
}));
};
};
transformer.for_property = function (obj_promise, prop) {
return function (/* ... */) {
var args = arguments;
return result_transformer(when(obj_promise, function (obj) {
return obj[prop].apply(obj, args);
}));
};
};
return transformer;
}
// Produces a transformer that takes a promised function
// taking a callback, and returns a function returning a promise,
// optionally transforming that promise.
function promisify_cb_func(result_transformer) {
result_transformer = result_transformer || identity;
var transformer = function (func_promise) {
return function (/* ... */) {
var args = arguments;
return result_transformer(when(func_promise, function (func) {
var d = when.defer();
func.apply(null, append(args, function (err, val) {
if (err) {
d.reject(err);
} else {
d.resolve(val);
}
}));
return d.promise;
}));
};
};
transformer.for_property = function (obj_promise, prop) {
return function(/* ... */) {
var args = arguments;
return result_transformer(when(obj_promise, function (obj) {
var d = when.defer();
obj[prop].apply(obj, append(args, function (err, val) {
if (err) {
d.reject(err);
} else {
d.resolve(val);
}
}));
return d.promise;
}));
};
};
return transformer;
}
// Produces a transformer that takes a promised object, and returns an
// object with the properties transformed according to the template.
function promisify_object(template) {
var transformer = function (obj_promise) {
var res = {};
for (var prop in template) {
res[prop] = template[prop].for_property(obj_promise, prop);
}
return res;
};
transformer.for_property = function (parent_promise, prop) {
return transformer(when(parent_promise, function (obj) {
return obj[prop];
}));
};
return transformer;
}
// Takes a promised read stream and returns a PStream
function promisify_read_stream() {
var transformer = function (stream_promise) {
var res = new PStream();
res.to = function (dest) {
when(stream_promise, function (stream) {
PStream.wrap_read_stream(stream).to(dest);
}, function (err) {
dest.error(err);
});
};
return res.sanitize();
};
transformer.for_property = function (obj_promise, prop) {
return transformer(when(obj_promise, function (obj) {
return obj[prop];
}));
};
return transformer;
}
exports.value = promisify_value;
exports.func = promisify_func;
exports.cb_func = promisify_cb_func;
exports.object = promisify_object;
exports.read_stream = promisify_read_stream;
exports.PStream = PStream;
;