如何promisify一个不包含callback参数的函数?

我目前正在工作一个API /路由器将被集成在用户自己的networking服务器。 我的代码将完成其所需的工作,但也允许用户实现自己的逻辑,如在这个片段: myApi.on('action', (err, result, req, res) => {/*user's logic here*/})

通过devise,如果用户决定重写默认行为并实现自己的逻辑,我的代码将不会结束响应。 这是为了允许用户在需要时响应下一个中间件function。

我期望的控制stream程是:

  1. 运行我的初始路由逻辑

  2. 运行用户的自定义逻辑

  3. 如果响应尚未结束,则将控制权交给下一个中间件function

我的问题出现在用户想要实现任何asynchronous逻辑时。 在将控制权交给下一个中间件function之前,我无法让用户的定制逻辑结束。 我相信这是因为我设置的界面。 我希望尽可能less的忙碌工作由用户来执行。 这意味着我不希望传递给用户一些他们需要在逻辑的每个端点上调用的callback()next()函数的等价物(因为我的路由器涉及许多不同的路由)。

我已经研究了promisify-node等承诺包装器,但是他们似乎只能包装那些以callback为最终参数的函数。 我也考虑要求用户从自定义实现中返回一个承诺,但是这违背了我不希望繁忙/样板代码的愿望。

有什么方法使用承诺 – 或任何其他构造 – 我可以处理这个asynchronous问题,而不必痛苦用户?

不,你不能promisify一个函数,不要callback。 这样的function或者不是asynchronous的,或者不能让你知道什么时候完成 – 你运气不好。

我的问题出现在用户想要实现任何asynchronous逻辑时。

只需要用户传递一个函数返回一个承诺,如果他想实现asynchronous的东西。 无论如何,这可能会让他有一个不得不承诺的承诺:-)

 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的对象,那么在继续之前可以等待它parsing。 这相当于将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. }); 

如果你想提供承诺 nextcallback你可以做这样的事情:

 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. }); 

由于承诺只能处理一个解决scheme,并且在设置之后会忽略更多的咒语,这将会起作用,并且哪个用户使用( next或者返回一个Promise)将会起​​作用。