我有以下情况。
我有一个服务,可在远程服务上运行作业,并公开用于调用该服务的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);
})
})
}
答案 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