如何宣传一个不包含回调参数的函数?

时间:2016-09-21 21:10:01

标签: javascript node.js promise

我目前正在使用一个API /路由器,它将集成在用户自己的Web服务器中。我的代码将执行其必需的工作,但也允许用户之后实现自己的逻辑,例如在此代码段中:myApi.on('action', (err, result, req, res) => {/*user's logic here*/})

按照设计,如果用户决定覆盖默认行为并实现自己的逻辑,我的代码将不会结束响应。这是为了允许请求和响应在用户需要时进入下一个中间件功能。

我想要的控制流程是:

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

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

  3. 如果响应尚未结束,则将控制权传递给下一个中间件功能

  4. 当用户想要实现任何异步逻辑时,我的问题就出现了。在将控制传递给下一个中间件函数之前,我无法允许用户的自定义逻辑结束。我相信这是因为我设置的界面。我希望尽可能少的繁忙工作由用户执行。这意味着我不希望向用户传递一些等价的callback()next()函数,这些函数需要在逻辑的每个端点调用(因为我的路由器涉及许多不同的路由)。 / p>

    我已经研究了诸如promisify-node之类的promise包装器,但它们似乎只能包装以回调作为最终参数的函数。我还考虑过要求用户从他们的自定义实现中返回一个承诺,但这违背了我不需要繁忙工作/样板代码的愿望。

    有没有办法使用promises - 或任何其他构造 - 我可以处理这个异步问题而不必痛苦用户?

2 个答案:

答案 0 :(得分:2)

不,你不能宣传一个不接受回调的功能。这样的功能要么不异步,要么没有任何方式知道它什么时候结束 - 你运气不好。

  

当用户想要实现任何异步逻辑时,我的问题就出现了。

如果他想要实现异步的东西,只需要用户传递一个返回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
})

答案 1 :(得分:0)

如果我理解了这个问题,你会检查用户的价值'自定义函数返回。如果它是类似承诺的对象,那么您可以在继续之前等待它解决。这相当于将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.
});

由于promises只能处理一个解决方案并且在设置之后忽略了进一步的咒语,这将起作用,并且用户使用(next或返回Promise)将会有效。