I would like to make an aggregated request, in particular I would like to make an initial request and several subrequest depending on the response of the initial request. Then I would like to return the result of all subrequest.
I used an approach with Promise.all():
function get_orders_with_places(r) {
r.subrequest('/orders')
.then(response => get_places(JSON.parse(response.responseBody), r))
.catch(error => r.return(error.stack));
}
function get_places(orders, r) {
var promises = [];
for (var i = 0; i < orders.length; i++) {
orders[i].warehousePlaces = [];
promises.push(r.subrequest('/location/' + orders[i].productName)
.then(function(response) {
var pallets = response.responseBody;
for (pallet in pallets) {
orders[i].warehousePlaces.push(pallet.storageLocation);
}
})
);
}
Promise.all(promises).then(() => r.return(200, JSON.stringify(orders)));
}
md5-13e82dc227da5bd072bb53a9f293696c
async function get_places(orders, r) {
for (var i = 0; i < orders.length; i++) {
orders[i].warehousePlaces = [];
var pallets = await r.subrequest('/location/' + orders[i].productName);
for (pallet in pallets) {
orders[i].warehousePlaces.push(pallet.storageLocation);
}
}
r.return(200, orders);
}
But I think async/await is not supported in njs.
I kind of ran out of ideas here. So any help would be much appreciated,
Hi @Jurilz
I think that I can implement Promise.all().
Hi @Jurilz
I think that I can implement Promise.all().
That would be really awesome and help me a lot.
Thank you.
@Jurilz
Here's the simplified Promise.all() polyfill:
function all(promises) {
return new Promise((resolve, reject) => {
var n = promises.length;
var rs = Array(n);
var done = () => {
if (--n === 0) {
resolve(rs);
}
};
promises.forEach((p, i) => {
p.then((x) => { rs[i] = x; }, reject).then(done);
});
});
}
all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)])
.then((rs) => console.log(rs));
Promise { <pending> }
> [ 1, 2, 3 ]
@lexborisov
And Promise.race() pls.
Here's the simplified
Promise.all()polyfill:
Thanks @drsm for your polyfill, I really think it should do the trick, but strangely enough I get a 500 Internal Server Error response from my subrequest-endpoint, although the /orders and the /location/ endpoint work fine.
I'm using it like this:
function get_orders_with_places(r) {
r.subrequest('/orders')
.then(response => get_places(JSON.parse(response.responseBody), r))
.catch(error => r.return(error.stack));
}
function get_places(orders, r) {
var promises = [];
for (var i = 0; i < orders.length; i++) {
orders[i].warehousePlaces = [];
promises.push(r.subrequest('/location/' + orders[i].productName)
.then(function(response) {
var pallets = response.responseBody;
for (pallet in pallets) {
orders[i].warehousePlaces.push(pallet.storageLocation);
}
})
);
}
resolveAll(promises)
.then(() => r.return(200, JSON.stringify(orders)));
}
function resolveAll(promises) {
return new Promise((resolve, reject) => {
var n = promises.length;
var rs = Array(n);
var done = () => {
if (--n === 0) {
resolve(rs);
}
};
promises.forEach((p, i) => {
p.then((x) => { rs[i] = x; }, reject).then(done);
});
});
}
Unfortunately I can't narrow down the error, even if I write a catch after every .then() I don't get the error stack.
@Jurilz
- resolveAll(promises)
+ return resolveAll(promises)
related to #346
And the reason:
$ node
Welcome to Node.js v12.19.0.
Type ".help" for more information.
> .editor
// Entering editor mode (^D to finish, ^C to cancel)
for (var i = 0; i < 10; ++i) {
Promise.resolve().then(() => console.log(`i = ${i}`));
}
Promise { <pending> }
> i = 10
i = 10
i = 10
i = 10
i = 10
i = 10
i = 10
i = 10
i = 10
i = 10
Related to #105
It's better to avoid loops when doing promises (without async/await):
function get_places(orders, r) {
var on_location = (order, response) => {
var pallets = JSON.parse(response.responseBody);
order.warehousePlaces = pallets.map((x) => x.storageLocation);
}
return resolveAll(
orders.map((x) => {
x.warehousePlaces = [];
return r.subrequest('/location/' + x.productName).then(on_location.bind(null, x));
})
)
.then(() => r.return(200, JSON.stringify(orders));
}
It's better to avoid loops when doing promises (without
async/await):
You Sir, just made my day. Everything works as intended with your approach. And I additionally learned something about promises.
Thank you very much. 袘芯谢褜褕芯械 褋锌邪褋懈斜芯.
@lexborisov Hi! Thank you help for implementation Promise.all https://github.com/nginx/njs/issues/352#issuecomment-719942062
Excuse for troubling. Do you have any news about this issue?
Most helpful comment
Hi @Jurilz
I think that I can implement Promise.all().