我目前正在使用一个API/路由器,该路由器将集成到用户自己的web服务器中。我的代码将完成它所需的工作,但也允许用户在之后实现他们自己的逻辑,例如在这个片段中:myApi.on('action', (err, result, req, res) => {/*user's logic here*/})
。
根据设计,如果用户决定覆盖默认行为并实现自己的逻辑,我的代码将不会结束响应。这是为了允许请求和响应在用户需要的情况下进入下一个中间件功能。
我想要的控制流程是:
-
运行我的初始路线逻辑
-
运行用户的自定义逻辑
-
如果响应未结束,则将控制权传递给下一个中间件功能
当用户想要实现任何异步逻辑时,就会出现我的问题。在将控制权传递给下一个中间件功能之前,我无法允许用户的自定义逻辑结束。我相信这是因为我设置的接口。我希望用户尽可能少地从事繁忙的工作。这意味着我宁愿不向用户传递callback()
或next()
函数的等效函数,用户需要在其逻辑的每个端点调用该函数(因为我的路由器涉及许多不同的路由(。
我研究过promise包装器,比如promisify节点,但它们似乎只能包装以回调作为最终参数的函数。我还考虑过要求用户从他们的自定义实现中返回promise,但这违背了我不需要busywork/样板代码的愿望。
有没有任何方法可以使用promise或任何其他构造来处理这个异步问题而不必让用户感到痛苦?
否,您不能承诺一个不接受回调的函数。这样的函数要么不是异步的,要么没有提供任何方法来知道它何时完成——你运气不好。
当用户想要实现任何异步逻辑时,就会出现我的问题。
如果用户想要实现异步的东西,只需要传递一个返回promise的函数。无论如何,这可能会帮他一个忙,因为他必须履行承诺:-(
const myApi = {
on(name, fn) {
Promise.resolve(result) // or whenever you need to run the user logic
.then(result =>
fn(req, result) // or whatever you want to pass
)
.then(customresult => {
res.write(customresult); // or whatever you want to do with its result
});
}
};
myApi.on('action', (req, result) => {
// user's logic here
// throw exceptions
// return values
// return promises for values
// or whatever the user needs to do
})
如果我理解这个问题,您将检查用户自定义函数返回的值。如果它是一个类似promise的对象,那么您可以等待它解析后再继续。这相当于将next
函数传递给用户的自定义中间件。
在您的示例中,用户将使用您的API,如下所示:
myApi.on('action', (err, result, req, res) => {
return myPromiseAwareAsyncFunction();
})
在你的代码中:
let userMiddleWare = lookupNextActionHandler();
let result = userMiddleWare(err, result, req, res);
// Wrap any value (promise or not) in a promise
Promise.resolve(result)
.then(result => {
// Move on to next middle ware
})
.catch(error => {
console.error(error);
process.exit(1); // Or what ever you use
// to end the middle ware chain.
});
如果你想同时提供和的承诺next
回调,你可以这样做:
let userMiddleWare = lookupNextActionHandler();
new Promise((resolve, reject) => {
function next(err) {
if (err) {
reject(err);
} else {
resolve();
}
}
let result = userMiddleWare(err, result, req, res, next);
Promise.resolve(result).then(resolve).catch(reject);
})
.then(result => {
// Move on to next middle ware
})
.catch(error => {
console.error(error);
process.exit(1); // Or what ever you use
// to end the middle ware chain.
});
由于Promise只能处理一个解析,并且在设置后会忽略其他咒语,因此这将起作用,并且用户使用的任何一个(next
或返回Promise(都将起作用。