2017-12-01 18 views
1

私はこのスタブのようなREST APIを使っています:Snippet 1(Ruby on Railsの例)。なぜjQueryのPromise.rejectが機能しないのですか?

私は、古典的なコールバックにjQueryのコードを既存している:あるSnippet 2

は丸太で実行されます。

case 1: 
[INFO] /api/my/action1: got rejecting signal, do not continue 

case 2: 
[INFO] /api/my/action1: no rejecting signal, continue 
[INFO] /api/my/action2: no rejecting signal, continue 
[INFO] /api/my/action3: hurrah!! we got message: Third action executed! 

case 3: 
[INFO] /api/my/action1: no rejecting signal, continue 
[ERROR] Got error with message: Unexpected error 

私は約束にこのコードをリファクタリングしたい:

function ajxGet(url){ 
    return $.ajax({ 
    url, 
    dataType: 'JSON' 
    }) 
} 

export function makeThreeAsyncQueries(){ 
    ajxGet('/api/my/action1') 
    .then(response1 => { 
     if(response1.do_reject_other_actions){ 
     console.log('[INFO] /api/my/action1: got rejecting signal, do not continue'); 
     return Promise.reject({mute: true}); 
     }else{ 
     console.log('[INFO] /api/my/action1: no rejecting signal, continue'); 
     return ajxGet('/api/my/action2'); 
     } 
    }) 
    .then(response2 => { 
     if(response2.do_reject_other_actions){ 
     console.log('[INFO] /api/my/action2: got rejecting signal, do not continue'); 
     return Promise.reject({mute: true}); 
     }else{ 
     console.log('[INFO] /api/my/action2: no rejecting signal, continue'); 
     return ajxGet('/api/my/action3'); 
     } 
    }) 
    .then(response3 => { 
     console.log('[INFO] /api/my/action3: hurrah!! we got message: ', response3.message); 
    }) 
    .fail((err) => { 
     if(err && err.mute){ 
     console.log('[INFO] normal chain break.'); 
     return 
     } 
     console.info('[ERROR] Got error with message:', err.responseJSON.message); 
    }); 
} 

問題Promise.reject({mute: true});は機能しません。これらのログは次のとおりです。

[INFO] /api/my/action1: got rejecting signal, do not continue   <<-- SHOULD STOP HERE 
[INFO] /api/my/action2: no rejecting signal, continue 
    Uncaught (in promise) Object {mute: true} 
    <...callstack here...> 
[INFO] /api/my/action3: hurrah!! we got message: Third action executed! 

答えて

1

例では、jQueryのDeferred約束のようなオブジェクトの代わりにECMAScript 2015 specificationPromiseを使用しています。

return Promise.reject({mute: true}); 

使用この:コードの

return $.Deferred().reject({ mute: true }) 

全例:

function ajxGet(url){ 
    return $.ajax({ 
    url, 
    dataType: 'JSON' 
    }) 
} 

export function makeThreeAsyncQueries(){ 
    ajxGet('/api/my/action1') 
    .then(response1 => { 
     if(response1.do_reject_other_actions){ 
     console.log('[INFO] /api/my/action1: got rejecting signal, do not continue'); 
     return $.Deferred().reject({ mute: true }) 
     }else{ 
     console.log('[INFO] /api/my/action1: no rejecting signal, continue'); 
     return ajxGet('/api/my/action2'); 
     } 
    }) 
    .then(response2 => { 
     if(response2.do_reject_other_actions){ 
     console.log('[INFO] /api/my/action2: got rejecting signal, do not continue'); 
     return $.Deferred().reject({ mute: true }) 
     }else{ 
     console.log('[INFO] /api/my/action2: no rejecting signal, continue'); 
     return ajxGet('/api/my/action3'); 
     } 
    }) 
    .then(response3 => { 
     console.log('[INFO] /api/my/action3: hurrah!! we got message: ', response3.message); 
    }) 
    // as argument here we will get jquery's xhr object on AJAX-error, or will get payload sent by $.deferred().reject 
    .fail((xhr) => { 
     if(xhr && xhr.mute){ 
     console.log('[INFO] normal chain break.'); 
     return 
     } 
     console.info('[ERROR] Got error with message:', xhr.responseJSON.message); 
    }); 
} 

だからバックエンドが壊れるdo_reject_other_actions === trueチェーンを返して、あなたなりますので、代わりにこのラインの

この正しいログを取得します:

[INFO] /api/my/action1: got rejecting signal, do not continue 
[INFO] normal chain break. 

or 

[INFO] /api/my/action1: no rejecting signal, continue 
[INFO] /api/my/action2: got rejecting signal, do not continue 
[INFO] normal chain break. 

or 

[INFO] /api/my/action1: no rejecting signal, continue 
[INFO] /api/my/action2: no rejecting signal, continue 
[INFO] /api/my/action3: hurrah!! we got message: Third action executed! 

or 

[INFO] /api/my/action1: no rejecting signal, continue 
[ERROR] Got error with message: Unexpected error 

SOLUTION 2

あなたがECMAScript2015 Promiseを使用する場合は、jQueryのajaxPromiseにラップすることができます:代わりにfail(...)のあなたは鎖の末端にcatch(...)を使用する必要があります

function ajxGet(url){ 
    return new Promise((resolve, reject) => { 
    $.ajax({ 
     url, 
     dataType: 'JSON', 
     success: response => resolve(response), 
     error: (xhr) => { reject(xhr) }, 
    }) 
    }); 
} 

export function makeThreeAsyncQueries(){ 
    ajxGet('/api/my/action1') 
    .then(response1 => { 
     if(response1.do_reject_other_actions){ 
     console.log('[INFO] /api/my/action1: got rejecting signal, do not continue'); 
     return Promise.reject({mute: true}); 
     }else{ 
     console.log('[INFO] /api/my/action1: no rejecting signal, continue'); 
     return ajxGet('/api/my/action2'); 
     } 
    }) 
    .then(response2 => { 
     if(response2.do_reject_other_actions){ 
     console.log('[INFO] /api/my/action2: got rejecting signal, do not continue'); 
     return Promise.reject({mute: true}); 
     }else{ 
     console.log('[INFO] /api/my/action2: no rejecting signal, continue'); 
     return ajxGet('/api/my/action3'); 
     } 
    }) 
    .then(response3 => { 
     console.log('[INFO] /api/my/action3: hurrah!! we got message: ', response3.message); 
    }) 
    .catch((xhr) => { 
     if(xhr && xhr.mute){ 
     console.log('[INFO] normal chain break.'); 
     return 
     } 
     console.info('[ERROR] Got error with message:', xhr.responseJSON.message); 
    }); 
} 

注意をfailはjQuery Deferredのメソッドです。