I have created a route in my REST API that produces a random food order for the user after they send a request with a bunch of parameters. I have a while loop that loops through potential options and places them into the randomOrder
array. The loop will run until there are as many items in the random order as numberOfHeads
specified by the user. The issue is that sometimes it is impossible to create an order that has something for all mouths to feed and as a result, the loop will run forever. As a backstop for this, I would like to add two conditions to the while loop
If the amount of items in the random order array matches the numberOfHeads
specified by the user then the loop can stop.
if it tried to do this for a number of seconds but finds itself looping infinitely, I want the loop to stop and simply serve up what it has managed to place in the randomOrder
array. I have tried to implement this with the setTimeout()
method but I can't seem to get it to change the keepCalling
Boolean from true
to false
in order to stop the loop. I am also not sure if I can feed two conditions into a while loop where if either condition becomes true the loop stops?
// RANDOM ORDER FILTER/GENERATOR
router.get("/randomorder", async (req, res) => {
//USERS CHOSEN CATEGORIES SPH & NOP SENT THROUGH THE REQUEST
const restCats = await req.body.restcategories
const menueCats = await req.body.menuecats
var totalSpend = await req.body.totalspend
const numberOfHeads = await req.body.numberofheads
const spendPerHead = totalSpend / numberOfHeads
console.log(spendPerHead)
let restOptions = await Restaurant.aggregate(
[{
$match: {
categories: {
$in: restCats
}
}
}]
)
let randomRestOption = restOptions[Math.floor(Math.random() * restOptions.length)];
//RESULT OF ALL MENUE ITEMS MATCHING USER CATEGORIES
let menueOptions = []
//FULL RESULT OF BOTH RESTURANTS MATCHING USERS CHOSEN CATEGORIES AND MENUE ITEMS OF THOSE RESTURANTS MATCHING USERS CATEGORIES
// LOOPS THROUGH ALL RESTURANT OPTIONS MENUES AND OUTPUTS MENUE ITEMS MATCHING THE USERS CHOSEN CATEGORIES
randomRestOption.menue.filter(function checkoptions(option) {
for (let x = 0; x < option.categories.length; x++) {
// console.log(option)
if (option.categories[x] === menueCats[0] || option.categories[x] === menueCats[1] || option.categories[x] === menueCats[2] || option.categories[x] === menueCats[3] || option.categories[x] === menueCats[4] || option.categories[x] === menueCats[5] || option.categories[x] === menueCats[6]) {
// FILTERS RESULTS BASED ON TOTAL SPEND PER HEAD CHOSEN BY USER
if (option.price <= spendPerHead) {
menueOptions.push(option)
} else if (spendPerHead === undefined) {
menueOptions.push(option)
}
}
}
})
var keepCalling = true
const myTimeout = setTimeout(reAssign, 3000)
function reAssign() {
keepCalling = false
}
myTimeout
let randomOrder = []
console.log(keepCalling)
while (randomOrder.length < numberOfHeads || keepCalling === true) {
// console.log(keepCalling)
let randomMenueOption = menueOptions[Math.floor(Math.random() * menueOptions.length)];
// console.log(randomMenueOption)
function checkDuplicates() {
let duplicate = ""
let itemName = randomMenueOption.name
// console.log(itemName)
for (let i = 0; i < randomOrder.length; i++) {
if (itemName === randomOrder[i].name) {
duplicate = "duplicate"
}
// console.log("loop running")
}
// console.log(randomOrder)
return duplicate
}
let checkduplicate = checkDuplicates()
if (checkduplicate === "duplicate") {
// console.log("Found Duplicate")
} else {
randomOrder.push(randomMenueOption)
}
randomOrder.length;
// console.log(randomMenueOption)
}
// console.log(spendPerHead)
try {
res.status(201).send({
randomOrder
})
} catch (err) {
console.log(err)
}
})
setTimeout
is an asynchronous
that means that it will be executed by the event loop
when the call stack
is empty .
So in your use case it will never will execute because the loop will occupy the call stack
.
If you want to get the same effect, you can use the Date
object to capture the current time, and in each iteration in the check if it passed the timeTocancel
.
let keepCalling = true;
const startingTime = Date.now();
const timeTocancel = 3000;
while (keepCalling) {
const currentTime = Date.now();
if (currentTime - startingTime >= timeTocancel ) break;
console.log("do things");
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.