2016-09-21 15 views
0

私は、希望の結果が返されるまで、一連のAJAX呼び出しをAPIに行う、JavaScript送信ハンドラに遅延チェーンを持っています。それはうまくいきましたが、私は微調整を行いましたが、今どこで間違っていたのか分かりません。なぜなら、新しいコードは約束が壊れているようです。遅延が解決されていません

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を後に再度試みますジョブを見つけてdataを記録し、最後に私が解決する直前に、私たちが条件付きにしたことを証明するコンソールメッセージを追加します。

しかし、その後console.log('got job status, updating and resolving');は発火しません - waitForJobStatusは解決されません、私は推測するので、createLinkAPIJobthen

答えて

1

を発射したことがないあなたは、問題領域を誤認しました。そのifブランチでは、遅延は正常に解決されます。問題はelseブランチです:ここでは

… else { 
    return $.promiseDelay(1000).then(function() { 
    return waitForJobStatus(jobID, timeStarted); 
    }); 
} 

defは解決されることはありません(とのいずれかrejctedされていません)!これはdeferred antipatternの使用に由来します。延期を使用していない場合はthenコールバックからのreturnが実際に機能します。あなたは、そのような連鎖だけをすることになっています。すでに約束を返す関数を呼び出す場合は、延期を作成しないでください(既に$.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 …; 
    }); 
} 
+0

回答とサンプルコードをありがとうございました。この回答は昨日(私が過去数ヶ月にわたって約束したほとんどの回答のように)私には半分しか意味がありませんでした - 私は約束したJavaScriptを買って昨日と今朝、それはずっと遅れていました。もう約束を誤解してここに来ることはありませんか? – fildred13

関連する問題