2

I am a beginner at web development and currently learning React, Redux and Node. I am trying to develop a smart-parking simulation application. I have already developed a Node rest api. I have another single page application built using React and Redux.

I have assumed 7 parking places in a city(every parking place has a specific latitude and longitude). Every 5 seconds, I am assuming a car comes for parking at a random place. As soon as car appears, my application call the node-api getOptimalParking and with certain algorithm it determines a parking place where it should be parked.

Now suppose a car 1 is assigned a parking place 1 and distance between them is 7 km. I am assuming it takes 1 sec to travel 1 km, hence car 1 will take 7 secs to reach parking place 1. After 7 seconds my react application will call an api substractOneParkingSlot.

What I want to achieve?

The thing I am unable to figure out is as every 5 seconds car Ci keeps coming and I have to wait for Si seconds for every car. As soon as Si reaches zero, I call an api. How to handle this thing i.e. how to wait for Si seconds before calling an api and meanwhile another car Cj can come and again for that I have to wait for Sj seconds independently.

Node-API list

getOptimalParking(userLat, userLng){
    return {
        distance: distance,
        lat: parkingLat,
        lng: parkingLng
    }
}

substractOneParkingSlot(parkingLat, parkingLng){
    if(parkingSlotAvailable) {
        currentParkingSlot -= 1
        return sucess
    }
    else 
        return failure
}

React-redux application working

As soon as car appears, I am calling a redux action that makes a request to getOptimalParking api and then I have another redux action that calls substractOneParkingSlot api after Ci seconds.

As I have multiple such concurrent call to redux actions, how to achieve this?

Thanks

EDIT:- For future readers, there is a very detailed answer available here.

Abhishek Kumar
  • 95
  • 2
  • 12

2 Answers2

2

Promises to the rescue, assuming you are already aware of them. Let have your actions like this:

const onParkedIntoSpace = id => dispatch => <call api and update some redux state>

const onGetParkingSpace = data => dispatch => {
    fetch('/parking', data)
        .then(position => {
            dispatch(<an action that will drive car to position>)

            return new Promise(resolve => {
                setTimeout(() => {
                    resolve(true)
                }, position.distance * 1000)
            })
        })
        .then((success) => {
            dispatch(onParkedIntoSpace())
        })
}

As promises can goes from one then to another, we can also change or send a new promise altogether. After the position is returned by the Node, a new promise is created and returned which will resolve the promised in distance seconds. Upon resolve in the second them we call the dispatch(onParkedInoSpace()).

The above code can also be scaled to have the new Promise to reject and be catched and inform Node that it's lost!

Update for additional changes: Two cars compete for the same space.

By the time the 1st car's setTimeout executes the 2nd car would have occupied it because it's closer.To solve this you need to change currentParkingSlot from a numeric value to an array of objects like this: { id: number, reserved: boolean; occupied: boolean }[]. When you allocate a parking space the id is passed and reserved is set to true. When the UI calls API upon parked the occupied is set to true. On a new parking request you filter the array to find available lots like this:

const parkingLots = [{
    id: 1,
    reserved: false,
    occipied: true,
    lat: 1.1,
    log: 1.1
}]

const getAnEmptyParkingLot = (parkingLots) => parkingLots.findIndex(lot => !lot.reserved || !lot.occipied)

const onRequestParkingLot = (request, response) => {
    const newLotIndex = getAnEmptyParkingLot(parkingLots)

    if (newLot > -1) {
        parkingLots[newLotIndex].reserved = true;
        response.
            .status(200)
            .json(newLot) // include distance
    } else {
        response.
            .status(200)
            .json({
                message: 'Sorry no space available'
            })
    }
}

const onParkedOntoLot = (request, response) => {
    const parkedToLot = parkingLots.findIndex(lot => lot.id === request.param.id)

    if (parkedToLotIndex > -1) {
        parkingLots.reserved = true;
        parkingLots.occipied = true;

        response.
            .status(200)
            .json({
                message: 'Parked onto lot'
            })
    } else {
        response.
            .status(400)
            .json({
                message: 'Cannot find the parking lot'
            })
    }
}
Vijay Dev
  • 1,024
  • 7
  • 14
  • Suppose at time t, car 1 is alloted space 1 and it will take 10 secs to reach parking space 1. Now my promise will wait for 10 secs before executing nested then. Suppose at time t+2, car 2 is also alloted space 1 and it will take 3 secs to reach parking space 1. Now, when car 2 reaches parking space 1 at time t+5, promise still needs to wait for 5 more secs for car 1 but it needs to call then for car 2. Is this thing handled automatically or I need to do something specific? – Abhishek Kumar Apr 01 '18 at 07:52
  • Thanks. I managed to solved the problem with the same idea but using redux-thunk – Abhishek Kumar Apr 01 '18 at 09:35
1

you could make use of the setTimeout() for each parking space indepentently.

  1. do your first api call
  2. setup you timeout for the appropriate duration in your api callback
  3. do the next step in the timeout's callback
  4. repeat as much as needed

setTimeout() doc on W3 school

frankybboy
  • 529
  • 5
  • 12