【问题标题】:How to continuously poll an API for a specific outcome in NodeJS?如何在 NodeJS 中持续轮询 API 以获取特定结果?
【发布时间】:2019-12-03 13:05:44
【问题描述】:

我已向 API 发出 HTTP PUT 请求,该 API 将响应状态返回为“等待”。我想继续使用 HTTP GET 请求轮询 API,直到状态变为“完成”。我在 NodeJS 中使用 Promise,但还没有找到持续轮询我的请求的解决方案。

我尝试过使用 setTimeout() 来使用 Promise Chaining,但这不会轮询 API,而是请求与我为 HTTP GET 编写代码一样多的次数。我想使用类似的东西:

while(JSON.parse(response.body).result.info.state != "finished")
{
  //keep polling
}

我应该在 API 控制台上看到轮询 GET 请求,但 while 循环只运行一次。

startRequest(request, reply) {

    console.log("startRequest() is fired")
    return new Promise((resolve, reject) => {

            setTimeout(function () {
                Request.put({ //making a PUT request (i have done require('request'))
                    headers: {
                        "SessionID": request.payload.session
                    },
                    url: "http://" + API - IP + ":" + API - PORT + "/upload/" + request.payload.filenameWithoutExtension,

                }, (error, response) => {
                    if (error)
                        reject(error);
                    else {
                        var state = JSON.parse(response.body).result.info.state;
                        var pendingid = JSON.parse(response.body).result.info.id;
                        console.log("response.body", response.body)
                        resolve(state + ":" + pendingid);
                    }
                })
            }, 3 * 1000)
        }).then(response => { //then with response making a GET request

                var infoArray = response.split(":")
                var pendingid = infoArray[1];

                return new Promise(function (resolve, reject) {
                        console.log("Polling() is fired")
                        while (state != "finished") {
                            Request.get({
                                headers: {
                                    "SessionID": request.payload.session
                                },
                                url: "http://" + API - IP + ":" + API - PORT + "/pending/" + pendingid,

                            }, (error, response) => {
                                if (error)
                                    reject(error);
                                else {
                                    state = JSON.parse(response.body).result.info.state;
                                    return state;
                                }
                            })
                        }
                    }
                }
            }

【问题讨论】:

  • @Bob 我想根据 HTTP PUT 请求中的响应发送重复的 HTTP GET 请求。通常响应是“等待”状态。我想触发相同的 HTTP GET 请求,直到我获得“完成”状态。
  • 您不能将while 循环与异步内容一起使用(除非您使用async/await 语法)。尝试递归方法。
  • @Bergi 在这种情况下如何使用 Async /await 语法?
  • @DevSenGoku Just like this
  • @Bergi 会试试这个并回复你。谢谢老兄。

标签: javascript node.js loops http promise


【解决方案1】:

一般来说,生效

while(variable !== value){
    asynchronousFunction(callback(){

    });       
}

正如预期的那样,如果异步函数正在同步执行,您可以使用 ;

f(){
    if(variable !== value){ // do the loop condition test
        asynchronousFunction(callback(){ //call the loop contents
            variable = updated_value ;// set the condition variable in the callback - ie. when asynchronousFunction is done. then..
            f() // call again - ie. loop with the updated condition variable
        });         
    }
}

f() ; // start the loop

虽然由于 Promise 和超时,这里的事情有点复杂;

试试

startRequest(request, reply) {
    console.log("startRequest() is fired")

    const pollingDelay = 1000 ;
    let state = null ;
    let pendingid = null ;

    return new Promise((resolve, reject) => {
            Request.put({ //making a PUT request (i have done require('request'))
                headers: {
                    "SessionID": request.payload.session
                },
                url: "http://" + API - IP + ":" + API - PORT + "/upload/" + request.payload.filenameWithoutExtension

            }, (error, response) => {
                if (error)
                    reject(error);
                else {
                    state = JSON.parse(response.body).result.info.state;
                    pendingid = JSON.parse(response.body).result.info.id;
                    console.log("response.body", response.body)
                    resolve(state + ":" + pendingid);
                }
            });
        }).then(response => { //then with response making a GET request
            return new Promise(function (resolve, reject) {                                            

                function pollState(){
                    console.log("Polling...")
                    Request.get({
                        headers: {
                            "SessionID": request.payload.session
                        },
                        url: "http://" + API - IP + ":" + API - PORT + "/pending/" + pendingid

                    }, (error, response) => {
                        if (error)
                            reject(error);
                        else {
                            state = JSON.parse(response.body).result.info.state;
                            continueCheckingForCompletion();
                        }
                    });                        
                }

                function continueCheckingForCompletion(){
                    if(state !== "finished")){
                        setTimeout(pollState,pollingDelay);
                    }
                    else{
                        resolve(state);
                    }
                }

                continueCheckingForCompletion();
            });
    });
}

免责声明

此代码(OP 代码的修改)仅用于解决重复调用异步函数(get)直到满足给定条件(状态 ===“完成”)的问题。

是否是正确的任务代码取决于请求包和服务器 API 的细节。

备注

检查“已完成”的“待处理”端点似乎并不直观。此外,如果提交被接受但随后由于某种原因未完成,“待处理”端点将需要引发错误以指示进程失败,否则轮询将无限期地继续。

这种类型的客户端使用更直观的 RESTful API 是;

/upload/<upload info> //success returns submission id

/status/<submissionId> // success returns current status - used for polling

/pending/[target identifier] //returns 404 - not here or the target if present in pending or discovery info if no target identifier.

/finished/[target identifier] //returns 404 - not here or the target if present in finished or discovery info if no target identifier.

【讨论】:

  • 你是个天才!我按照您的方法,可以成功轮询请求,并且能够从响应中解析结果。只需要在 JSON.parse() 周围给出一个 try-catch 块。
猜你喜欢
  • 1970-01-01
  • 2014-12-18
  • 2021-08-20
  • 1970-01-01
  • 2015-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多