【问题标题】:Javascript: How to check if async operation is still pending / In progress?Javascript:如何检查异步操作是否仍在挂起/进行中?
【发布时间】:2019-07-26 20:59:11
【问题描述】:

我想知道是否可以通过某种方式检查 Javascript 中的异步操作是否仍在等待中。 因为我正在对调用特定 URL 进行数据库请求...虽然 db 调用仍在进行中,但我想停止任何其他传入的 db-calls(这意味着,如果 db-请求仍在等待中)。 这有可能吗?

因为数据库调用最多需要几分钟,而且我不想在第一个数据库调用仍在进行时启动另一个数据库调用。问题是,我不知道如何检查调用是否已经开始并且仍在进行中,因为响​​应仅在进程已经完成时的 .then() 子句之后出现。

这是我的数据库调用函数:

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

        writeMessageObject = checkDocuments(...);

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

这是我的 URL/Route Call 函数,带有 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);
            };

    } 
});

【问题讨论】:

  • 也许在promise的开头和数据库操作的结尾放置一个标志,并检查它需要检查的地方。或者,修改serializability上的数据库隔离,事务应该一个接一个地发生,这样就不会有干扰。
  • “标志”是什么意思?我现在只是想知道我是否可以以某种方式将异步函数调用 getReadIndex() 分配给一个变量,例如 const a = getReadIndex();然后检查它是否挂起(因为它应该是一个承诺)?
  • 通过标志我的意思是创建一个全局变量,当输入承诺时将其值更改为1(运行),并在数据库的读取函数中将其值更改为0(完成)。然后,在运行下一个代码之前输入while(flag),或者只是检查它,如果不是0,请不要再进一步。
  • 一开始我也是这么想的,但这正是我的问题:当它运行时,你无法检查它是否真的在运行..如何检查我是否输入了promise?我可以在执行调用之前放置一个标志变量“running=true”,如果为真,我会返回。但是它一开始就永远不会执行该功能....
  • 我在这里找到了一个链接,如何在另一个函数中手动检查承诺的状态:ourcodeworld.com/articles/read/317/…,但我真的想知道是否无法以某种方式查询承诺的实际状态一种更简单的方法,例如使用静态字段 isPending 或类似的东西,Promises 中是否不存在一个本地字段,您可以在其中简单地查询 Promise 的实际状态?!

标签: javascript asynchronous pending-transition


【解决方案1】:

嗯,我在这里找到了解决方法: https://ourcodeworld.com/articles/read/317/how-to-check-if-a-javascript-promise-has-been-fulfilled-rejected-or-resolved

所以我编写了该函数来检查 promise stati,但我仍然想知道是否无法查询静态 promise 属性以获取其实际状态;)(但奇怪的是,我没有'在网上找不到任何东西)。

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;    
}

所以我为请求修复了我的函数:

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);
            };

    } 
});

【讨论】:

  • 为什么我的解决方案会减去 2?
【解决方案2】:

如果操作仍在运行,您需要尝试在 node.js 中添加 global.dbCallState 标志。

这个global var 1 适用于所有模块。 不要像global = new Object();那样改变这个对象,但你可以使用子字段。

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

您可以在另一个模块中更改它,例如 global.dbCallState = false

这不是最好的解决方案,但它可以提供帮助。


但我不知道,为什么你只想要一个连接。在 node.js 中阻塞 I/O 不是很好的解决方案

【讨论】:

  • 你甚至不需要一个全局的,一个静态变量(例如在模块范围内)就足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-07
  • 1970-01-01
  • 2015-04-24
相关资源
最近更新 更多