我有一个快速服务器,需要从每个请求的多个外部源获取一些数据。这个逻辑分成多个路由器(有些不是我管理的)。
这些路由器完全独立,因此无需等待另一台路由器。
作为一个例子,我有以下代码:
const router1 = express.Router();
const router2 = express.Router();
const router3 = express.Router();
const finalRouter = express.Router();
router1.use((req, res, next) => setTimeout(next, 2000));
router2.use((req, res, next) => setTimeout(next, 2000));
router3.use((req, res, next) => setTimeout(next, 2000));
finalRouter.use((req, res, next) => console.log('All done!'));
当我通常在我的应用程序中使用所有这些路由器时,它将按顺序执行并在6秒内打印All done!
。
但是为了提高我的页面速度,我想并行执行它们,所以它们都在2秒内完成。我怎么能这样做?
答案 0 :(得分:1)
此处绝对不需要个别路线,您可以只使用一条路线并使用Promise.all等待所有请求。如果他们不能自然地支持Promises,你可以将它们包装在一个例如
中router.use(async (req, res, next) => {
await Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => resolve(), 2000);
}),
...
]);
next();
});
router.use((req, res, next) => {
console.log('All done!');
});
根据评论中的讨论,如果你没有能力将路线合并为一个 - 这很好,并不重要。想想更多关于这一点,你真正需要的是一个包装来捕捉"真正的"中间件,将其添加到队列,然后转到下一个。为了实现这一点,您至少需要访问设置路由(它看起来具有)的代码,例如。
<强> queue.js 强>
module.exports = route => {
return (req, res, next) => {
// ensure we've got a queue
if (!(req.queue instanceof Array)) {
req.queue = [];
}
// queue the blocking route
req.queue.push(new Promise((resolve, reject) => {
// run real route, signal success or failure when done
route(req, res, err => err ? reject(err) : resolve());
});
next(); // move on, don't wait
};
}
然后在你的路线
const queue = require('./queue');
...
router.use(queue((req, res, next) => setTimeout(() => next(), 2000))));
router.use(queue((req, res, next) => setTimeout(() => next(), 2000))));
router.use(queue((req, res, next) => setTimeout(() => next(), 2000))));
router.use(async (req, res, next) => {
await Promise.all(req.queue);
console.log('All done!');
}
答案 1 :(得分:0)
您可以向所有子路由器发出虚假请求(通过滥用this回答中找到的内部句柄方法):
const mainroute = Express.Router();
mainroute.get("/",function(req,res,next){
Promise.all([
new Promise(resolve =>
router1.handle(req,res, resolve)),
new Promise(resolve =>
router2.handle(req,res,resolve))
]).then(_=>res.end("all done"));
});
也可以通过传递带有请求的promise数组手动实现,然后你可以在最后等待它们:
const router1 = express.Router();
const router2 = express.Router();
const timer = ms => new Promise( res => setTimeout(res,ms));
router1.use((req, res, next) =>{
req.promises = [timer(2000)];
});
router1.use( req => req.promises[0] = req.promises[0].then(_=>"first done"));
router2.use((req, res, next)=>req.promises.push(timer(2000)));
router1.use("/test",router2);
router1.use((req,res)=> Promise.all(req.promises).then(_=>res.end("all done")));