I.K.
I.K.

Reputation: 464

Multithreaded Request With Javascript

Hello everyone, I am trying to build a ReactJS App which controls and monitors the status of some physical devices. In order to get the status of these physical devices I am using a request that looks like :

axios.get('http://192.168.1.***:8080').then( response => {
    let deviceStatusMode = 0;
    if(response.data.isCritical) {
        deviceStatusMode = 1;
    } else if (response.data.isWarning) {
        deviceStatusMode = 2;
    } else {
        deviceStatusMode = 3;
    }
    let opvObj = {
        "odv1" : deviceStatusMode,
        "odv2" : 2,
        "odv3" : 3
    }
    store.dispatch(odvStatus(opvObj));
});

This request need to be sent to several devices (Nearly 9-10). However some of them will be closed, some of them may not answer, so whats the greatest way to avoid waiting this request timeouts and merging them by multithreading approach? Thanks!

Upvotes: 0

Views: 3870

Answers (2)

Noel Kriegler
Noel Kriegler

Reputation: 529

For "concurrency" in JS look at using Promise.all().

Check out https://hackernoon.com/concurrency-control-in-promises-with-bluebird-977249520f23 for more info.

Edit the below code as seen necessary but heres a rough outline

// assuming these are your devices
const devices = [1, 2, 3, 4, 5, 6, 7, 8, 9]

(async () => {
    // These were then passed to Promise.all() to be executed in parallel. 
    let opvObj = {};
    await Promise.all(devices.map(async (device) => {
        axios.get('http://192.168.1.***:8080')
            .then(response => {
                let deviceStatusMode = 0;
                if (response.data.isCritical) {
                    deviceStatusMode = 1;
                } else if (response.data.isWarning) {
                    deviceStatusMode = 2;
                } else {
                    deviceStatusMode = 3;
                }
                // build up opvObj
                opvObj[`odv${device}`] = deviceStatusMode;
            })
            .catch(error => {
                // do something with the error
                console.log(error)
            });
    }));
    //dispatch 
    store.dispatch(odvStatus(opvObj));
})()

Upvotes: 1

Jclangst
Jclangst

Reputation: 1342

There is no real concept of multithreading in javascript -- all of the execution takes place on a single thread. However, because javascript has an asynchronous event loop, we can still interoperate different parts of your code without having to wait for any http requests to finish.

Since it looks like you are using redux, all you have to do is keep the same code that you have right now, except you should update the state incrementally (i.e., just 'odv1' instead of 'odv1' - 'odv3' all at once. Take another look at the redux reducer docs for how to do that.

Then you can run make several axios.get calls right after each other. They won't block each other because of the asynchronous nature of javascript (i.e., the http requests will all be in flight at the same time, not executed strictly sequentially):

axios.get('/dev1').then(...);
axios.get('/dev2').then(...);
axios.get('/dev3').then(...);
axios.get('/dev4').then(...);
axios.get('/dev5').then(...);

For more information check out details about the js event loop.

If you really need to do some operations separate of the main gui thread (i.e., if you have 10,000+ device statuses you need to keep up to date second by second), you can check out web workers. Based on what you've shared, however, I think this will introduce more complexity than is necessary for your project.

Edit:

One of the above answers proposes Promise.all. While I like his method of extracting the core logic into its own function, using Promise.all simply combines all of the promises into one. This will still cause you to have to wait until the slowest of your devices responds before you update your store which is almost definitely not what you want. Again, performing incremental updates to the redux store as the http requests return is almost definitely going to be the fastest way to get the most up-to-date information to your user's screen.

Upvotes: 0

Related Questions