我在 javascript 提交处理程序中有一系列延迟函数,它对 API 进行一系列 AJAX 调用,直到返回所需的结果。它运行良好,但我做了一个调整,现在我无法弄清楚我错在哪里,因为新代码似乎有一个 splinter 的 promise 链。
function createLinkAPIJob(type) {
//code to create a request
return $.ajax(request)
}
function getJobStatus(jobID) {
return $.ajax({
url: Urls['find_job'](jobID),
contentType: 'application/JSON',
method: 'GET'
})
}
// utility function to create a promise that is resolved after a delay
$.promiseDelay = function(t) {
return $.Deferred(function(def) {
setTimeout(def.resolve, t);
}).promise();
}
function waitForJobStatus(jobID, timeStarted) {
return $.Deferred(function(def) {
getJobStatus(jobID).then(function(data) {
console.log(data);
var isFinished = data['job']['finished'];
var jobStatus = 'incomplete';
var jobStatus = data['job']['job_status'];
if (isFinished === true) {
/***** HERE IS THE PROBLEM AREA *****/
console.log('resolving wait for job status');
def.resolve(jobStatus);
//also tried: return jobStatus;
} else {
return $.promiseDelay(1000).then(function() {
return waitForJobStatus(jobID, timeStarted);
});
}
});
}).promise();
}
function executeLinkAPIJob(type) {
return $.Deferred(function(def) {
createLinkAPIJob(type).then(function(response) {
var jobID = response['data']['job_id'];
var timeStarted = new Date().getTime() / 1000;
console.log('waiting for job to finish');
waitForJobStatus(jobID, timeStarted).then(function(jobStatus) {
console.log('got job status, updating and resolving');
// A bunch of code here that doesn't matter for this issue...
def.resolve();
});
});
}).promise();
}
// I know this seems stupid in this example, but jobs is sometimes a longer array
jobs = [executeLinkAPIJob(type=type)]
.when.apply($, jobs).then(function() {
// do something
});
控制台输出为
waiting for job to finish
Object {job: "{"error": "Job not found"}"}
Object {job: Object}
resolving wait for job status
这是有道理的:第一行就在 waitForJobStatus
被调用之前,然后 waitForJobStatus
尝试一次但未能找到作业,然后在 1 秒后再次尝试并找到作业一个作业,因此它记录了数据
,最后在我解决之前,我添加了一条控制台消息来证明我们已将其纳入条件。
但是 console.log('got job status, update and resolving');
永远不会触发 - waitForJobStatus
没有得到解决,我猜,所以createLinkAPIJob
中的 then
永远不会触发
最佳答案
您错误地识别了问题区域。在该 if
分支中,延迟问题得到了很好的解决。问题是 else
分支:
… else {
return $.promiseDelay(1000).then(function() {
return waitForJobStatus(jobID, timeStarted);
});
}
在这里,def
永远不会解析(并且也不会被拒绝)!这源于您对 deferred antipattern 的使用- 如果您没有使用延迟,则从 then
回调返回确实可以工作。你应该只做这样的链接。如果您正在调用已经返回 Promise 的函数,则永远不要创建延迟(通过分解 $.promiseDelay
已经做得非常好)!
function waitForJobStatus(jobID, timeStarted) {
return getJobStatus(jobID).then(function(data) {
console.log(data);
var isFinished = data['job']['finished'];
var jobStatus = 'incomplete';
var jobStatus = data['job']['job_status'];
if (isFinished === true) {
console.log('resolving wait for job status');
return jobStatus; // this is correct indeed
} else {
return $.promiseDelay(1000).then(function() {
return waitForJobStatus(jobID, timeStarted);
});
}
});
}
function executeLinkAPIJob(type) {
return createLinkAPIJob(type).then(function(response) {
var jobID = response['data']['job_id'];
var timeStarted = new Date().getTime() / 1000;
console.log('waiting for job to finish');
return waitForJobStatus(jobID, timeStarted);
}).then(function(jobStatus) {
console.log('got job status, updating and resolving');
// A bunch of code here that doesn't matter for this issue...
return …;
});
}
关于javascript - 推迟并没有解决,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39627730/