2017-12-01 2 views
1

Ich arbeite mit REST API, ähnlich zu diesem Stub: Snippet 1 (Ruby on Rails Beispiel).Warum jQuery Promise.reject nicht funktioniert?

Ich habe eine vorhandene jQuery-Code auf klassische Rückrufe: Snippet 2

, die mit Protokollen ist ausführt:

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 

ich diesen Code zu Versprechen Refactoring wollen:

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); 
    }); 
} 

Das Problem ist das Promise.reject({mute: true}); funktioniert nicht, und ich habe diese Protokolle:

[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! 

Antwort

1

In Ihrem Beispiel verwenden Sie Promise von ECMAScript 2015 specification anstelle von jQuery Deferred Versprechen-ähnliches Objekt.

Also statt dieser Zeile:

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

verwenden:

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

Voll Beispiel Code:

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); 
    }); 
} 

Als Backend do_reject_other_actions === true Kette zurückkehren wird brechen und Sie wird diese korrekten Protokolle erhalten:

[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

Wenn Sie ECMAScript2015 Promise verwenden möchten, können Sie jQuery ajax in Promise wickeln:

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); 
    }); 
} 

Hinweis, dass anstelle von fail(...) müssen Sie catch(...) am Ende der Kette verwenden, , weil fail die Methode von jQuery Deferred ist.

Verwandte Themen