我想使用promise,但我有一个回调API,格式如下:
1.DOM加载或其他一次性事件:
window.onload; // set to callback
...
window.onload = function() {
};
2.普通回调:
function request(onChangeHandler) {
...
}
request(function() {
// change happened
...
});
3.节点样式回调(“nodeback”):
function getStuff(dat, callback) {
...
}
getStuff("dataParam", function(err, data) {
...
})
4.具有节点样式回调的整个库:
API;
API.one(function(err, data) {
API.two(function(err, data2) {
API.three(function(err, data3) {
...
});
});
});
我如何在promise中使用API,如何“promise”它?
在Node.js 8中,您可以使用此npm模块动态地promisify对象方法:
https://www.npmjs.com/package/doasync
它使用util.provify和代理,使对象保持不变。Memoization也使用WeakMaps完成)。以下是一些示例:
使用对象:
const fs = require('fs');
const doAsync = require('doasync');
doAsync(fs).readFile('package.json', 'utf8')
.then(result => {
console.dir(JSON.parse(result), {colors: true});
});
具有以下功能:
doAsync(request)('http://www.google.com')
.then(({body}) => {
console.log(body);
// ...
});
您甚至可以使用本机调用和应用来绑定某些上下文:
doAsync(myFunc).apply(context, params)
.then(result => { /*...*/ });
承诺总是有决心和拒绝。当您编写异步包装器时,只需调用resolve即可。
您可以为几乎所有接受回调的函数编写包装函数,如下所示:
const myAsyncWrapper = (...params) =>
new Promise((resolve, reject) =>
someFunctionWithCallback(...params, (error, response) =>
error ? reject(error) : resolve(response)
)
);
您可以进一步编写回调到promise的转换函数:
const promisify =
(functionWithCallback) =>
(...params) =>
new Promise((resolve, reject) =>
functionWithCallback(...params, (error, response) =>
error ? reject(error) : resolve(response)
)
);
当使用较旧的库或SDK时,包装函数的概念尤其有用。例如,考虑FacebookGraph API的JavaScriptSDK,它使用类似的回调结构来发出API请求。
FB.api(apiURL, options, function (request) {
if (request.error || !request) return;
// handle request
});
在现代应用程序中,使用基于承诺的API更有用。如果您只使用一个函数一次或两次,则最好单独给出响应:
// in an async function
const response = await new Promise((resolve, reject) =>
FB.api(apiURL, (res) => (res?.error ? reject(res?.error) : resolve(res)))
);
如果经常使用该函数,可以使用相同的包装器概念来编写如下函数:
const apiWrapper = (...params) =>
new Promise((resolve, reject) =>
FB.api(...params, (res) => (res?.error ? reject(res?.error) : resolve(res)))
);
虽然promisifier有时很好,但它们不适用于这样的特定实例。在这种情况下,在Github上寻找一个现代的包装器,或者像这样编写自己的包装器。
在Node.js 8中,您可以使用此npm模块动态地promisify对象方法:
https://www.npmjs.com/package/doasync
它使用util.provify和代理,使对象保持不变。Memoization也使用WeakMaps完成)。以下是一些示例:
使用对象:
const fs = require('fs');
const doAsync = require('doasync');
doAsync(fs).readFile('package.json', 'utf8')
.then(result => {
console.dir(JSON.parse(result), {colors: true});
});
具有以下功能:
doAsync(request)('http://www.google.com')
.then(({body}) => {
console.log(body);
// ...
});
您甚至可以使用本机调用和应用来绑定某些上下文:
doAsync(myFunc).apply(context, params)
.then(result => { /*...*/ });