javascript - 推迟并没有解决

标签 javascript jquery promise jquery-deferred deferred

我在 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/

相关文章:

javascript - 如果从 JSON.search() 返回 JavaScript 变量,为什么它是 "undefined"?

jquery - Asp.net:带有 Jquery slider 问题的 Repeater

javascript - Node.js:使用 Bluebird 将模块函数从回调转换为 Promise

javascript - 使用 Promises 从 DynamoDB 异步检索数据

javascript - 更改 AngularJS 输入范围的值

javascript - 在 Javascript 重定向中包含 HTTP 方法?

Javascript 在不滚动的情况下更改 window.location.hash,但仍会触发 CSS :target pseudo-class

php - 使用 jquery 收集 trid

javascript - 在 jquery 中获取 span 标签的前 2 个和后 2 个词

angularjs - 使用带有循环的 Protractor