调用外部API,直到请求被标记为完成

时间:2019-02-04 07:24:56

标签: node.js

我有以下情况。

我有一个服务,可在远程服务上运行作业,并公开用于调用该服务的API。

我有一系列作业,需要在远程服务器上执行,使用Promises时,它可以正常工作。

流程如下

在main函数内部,我得到了一个令牌。在相同的.then()上,我启动作业的for循环并传递JobID和令牌。第二个函数向我返回每个作业的execution_ID。在第二个函数的.then()上,我传递令牌和execution_id。这将返回我的工作状态。

我的问题是;执行作业时,它将状态发送给我排队,启动和完成。当状态变为“完成”时,我得到了工作结果;我需要显示。

我尝试在最后一个函数中使用setTimeOut(),但是由于每个作业可能需要不同的时间,因此我不确定何时结束。

是否有一种方法可以多次调用此第三函数,除非状态更改为“已完成”?

下面是代码

app.get('/ExecuteJobs', function (req, res) {
var commandArraay = ["job1", "job2"]
var sTokenID;
getAuthToken()
    .then(function (token) {
        commandArraay.forEach(function (element) {
            getExecutionID(token, element)
                .then(function (executionResult) {
                    setTimeout(() => {
                        getExecutionResult(token, executionResult.id, executionResult)
                            .then(function (updateArray) {
                                console.log("Final Status " + "ID: " + executionResult.id + " Status: " + executionResult.status);
                                // if(executionResult.)
                            })
                    }, 10000)

                })
        })

    })
res.send('Done');
});



// Function to get the auth token
async function getAuthToken(token) {
    return new Promise(function (resolve, reject) {
        process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
        var pUserID = 'uname'
        var pPwd = 'pwd'
        performhttpsRequest('/<remote_api>/tokens', 'POST', {
            sAuth: "Basic " + new Buffer(pUserID + ":" +    pPwd).toString("base64")
    }, "0", token,
        function (data1) {
            sTokenID = data1.token;
            resolve(sTokenID);
        })
})
}
// Function to post the command and get execution ID
async function getExecutionID(tokenID, command, executionID) {
    return new Promise(function (resolve, reject) {
        performhttpsRequest('/<remote_api>/executecommand', 'POST', {
        command: command
    }, "1", tokenID,
        function (data1) {
            var executionID = data1.execution_id;
            resolve(executionID);
        })
})
}
// Function to get the execution results for an ID
async function getExecutionResult(tokenID, executionID, result) {
return new Promise(function (resolve, reject) {
    performhttpsRequest('/<remote_api>/execution_result/' + executionID, 'GET', {

    }, "1", tokenID,
        function (result) {
            resolve(result.result);
        })
})

}

2 个答案:

答案 0 :(得分:1)

如果您在排队的工作得到解决后绝对需要结果,那么除了重新尝试每隔n秒检查一次状态之外,我看不到其他选择。

这就是我要做的。一个递归函数,它每次尝试等待n秒时,都会重试请求n次:

// Mock request, resolves { status: 'completed' } 20% of the time.
const request = () => {
  return new Promise(resolve => {
    Math.random() < 0.2
      ? resolve({ status: 'completed', foo: 'bar' })
      : resolve({ status: 'pending' })
  })
}

const retryToCompletion = async ({ wait, retries }) => {
  console.log('Retries left:', retries)

  const result = await new Promise((resolve, reject) => {
    setTimeout(() => request().then(resolve).catch(reject), wait)
  })

  if (result.status === 'completed')
    return result

  if (retries)
    return retryToCompletion({ wait, retries: --retries })

  throw new Error('Retry attempts exhausted')
}

retryToCompletion({ wait: 1000, retries: 5 })
  .then(console.log)
  .catch(console.error)

话虽这么说,一些与BASE队列一起使用的API提供了WebSocket连接的句柄,该句柄在作业完成时通知。如果API提供了此功能,那么您应该放弃重试,而使用完整的通知。

答案 1 :(得分:0)

进行GET通话直到完成

/**
 * cbk be called when..complete execution ok
 */
function completeExecution(tokenID, executionID, result, callPeriod, cbk){
    return getExecutionResult(tokenID, executionID, result).then(res=>{

        if(res.completed){
            return cbk(null, res)
        }

        setTimeout(function(){
            return completeExecution(cbk); //reenqueue
        }, callPeriod)
    }).catch(cbk) //up to you to abort or insist
}

然后,您可以completeExecution(或由您自己)保证util.promisify