2

I would like to know if it is somehow possible to check if an asynchronous operation in Javascript is still pending.. Because I am doing a database request on calling a specific URL... While the db call is still in progress, I want to stop any other incoming db-calls (which means, stop any further calls to that URL in case the db-request is still pending). Is that somehow possible?

Because the database call takes up to minutes, and I don't want to launch another database-call while the first is still in progress.. The problem is, I somehow cannot figure out how to check if the call has started and is still in progress, because the response comes only after the .then() clause when the process has already finished.

this is my db-call function:

const getWriteIndex = async () =>  {   
    return Promise.all(someFunction1, someFunction2...).then(...) {  

        writeMessageObject = checkDocuments(...);

        return Promise.resolve(writeMessageObject);       
       })).catch((err) => {           
           return Promise.reject(err);
       });
}

This is my URL/Route Call function with express:

router.get("/v1/...", someMiddleware(), async function(req,res,next) {    

    if (read_cached() && initialised_read) {
        res.setHeader('Content-Type', 'application/json');
        res.json(readmsg_obj);
    } else {    
        try {   
            //HOW CAN I CHECK HERE IF THE DB-CALL IS ALREADY IN PROGRESS?
                readmsg_obj.message = '';  
                getReadIndex().then((message) => {                       
                    initialised_read = true;
                    readmsg_obj = {...message};                
                    res.setHeader('Content-Type', 'application/json');
                    res.json(readmsg_obj);
                }).catch((reject) => {                  
                    logger.error(`/../... : ${reject}`);
                    initialised_read = false;
                    res.status(500).send(reject);
                });
            } catch(err)  {
                logger.error(`/v1/... : ${err}`);
                res.status(500).send(err);
            };

    } 
});
MMMM
  • 3,320
  • 8
  • 43
  • 80
  • 2
    Maybe put a flag at the start of the promise and at the end of the DB operation and check where it needs to be checked. Or, modify database's isolation on `serializability` and the transactions should occur one after the other, so there would be no interfering. – ClaudiusDan Mar 05 '19 at 11:45
  • What do you mean by "flag"? I am just wondering now if I can somehow assign the async function call getReadIndex() to a variable, e.g const a = getReadIndex(); and then check on a if its pending (because it should be a promise)? – MMMM Mar 05 '19 at 11:47
  • 1
    By flag I mean make a global var and when entering the promise change it's value to `1` (running) and in database's reading function change it's value to `0` (finished). Then, put a `while(flag)` before running your next code or just check it and if it is not `0`, do not go further. – ClaudiusDan Mar 05 '19 at 11:49
  • I thought the same at first, but that is exactly my problem: While it is running, you can not check if it is actually running.. How can I check if I entered the promise? I could place a flag variable "running=true" before I execute the call, and if true, I return. But then it would never execute the function in the first place.... – MMMM Mar 05 '19 at 11:54
  • I found a link here how to check the promise manually inside another function about its state: https://ourcodeworld.com/articles/read/317/how-to-check-if-a-javascript-promise-has-been-fulfilled-rejected-or-resolved , but I am really wondering if its not somehow possible to query for the actual state of the promise in a simpler way, e.g with a static field isPending or something like that, does there not exist a native field in Promises where you can simply query the actual state of the promise?! – MMMM Mar 05 '19 at 12:07
  • You could use a package like bottleneck to limit the concurrency of async requests to one https://www.npmjs.com/package/bottleneck – Ross Coundon Mar 05 '19 at 12:41
  • What is `initialised_read`? You should use it, or make a flag exactly like it, to record whether a `getWriteIndex` is currently in progress. (Although I agree with @ClaudiusDan, this should best be fixed at the database layer) – Bergi Mar 05 '19 at 13:05
  • Possible duplicate of [How can I synchronously determine a JavaScript Promise's state?](https://stackoverflow.com/questions/30564053/how-can-i-synchronously-determine-a-javascript-promises-state) – Scott Rudiger Mar 07 '19 at 10:11

2 Answers2

0

hmm I found a workaround here: https://ourcodeworld.com/articles/read/317/how-to-check-if-a-javascript-promise-has-been-fulfilled-rejected-or-resolved

so I wrote that function to check for promise stati, but I am still wondering if it's not somehow possible to query for static promise properties to get their actual state ;) (but weirdly, I didn't find any on the web).

const checkPendingRequest= (promise) => {
    if (promise.isResolved) return promise;    
        // Set initial state
        var isPending = true;
        var isRejected = false;
        var isFulfilled = false;

        // Observe the promise, saving the fulfillment in a closure scope.
        var result = promise.then(
            function(v) {
                isFulfilled = true;
                isPending = false;
                return v; 
            }, 
            function(e) {
                isRejected = true;
                isPending = false;
                throw e; 
            }
        );

        result.isFulfilled = function() { return isFulfilled; };
        result.isPending = function() { return isPending; };
        result.isRejected = function() { return isRejected; };
        return result;    
}

So I fixed my function for the request:

router.get("/v1/...", someMiddleware(), async function(req,res,next) {    

    if (read_cached() && initialised_read) {
        res.setHeader('Content-Type', 'application/json');
        res.json(readmsg_obj);
    } else {    
        try {   
           readmsg_obj.message = '';  

            if ((dbQueryPromiseRead != null) && dbQueryPromiseRead.isPending()) {
                logger.info(`Database request for Index-read is still pending!`);
                return;
            }

            dbQueryPromiseRead =  checkPendingRequest(getReadIndex());

            dbQueryPromiseRead.then((message) => {  
                initialised_read = true;
                readmsg_obj = {...message};

                res.setHeader('Content-Type', 'application/json');
                res.json(readmsg_obj);
                }).catch((reject) => {                  
                    logger.error(`/../... : ${reject}`);
                    initialised_read = false;
                    res.status(500).send(reject);
                });
            } catch(err)  {
                logger.error(`/v1/... : ${err}`);
                res.status(500).send(err);
            };

    } 
});
MMMM
  • 3,320
  • 8
  • 43
  • 80
0

You need to try add in node.js like global.dbCallState flag if operation is still running.

This global var one for all modules. Do not change this object like global = new Object();, but you can use child field's.

https://nodejs.org/api/globals.html

You can change it in another module like global.dbCallState = false.

It not best solution, but it can help.


But i don't know, why you want only one connection. Its not good solution to block I/O in node.js