我是否总是需要catch(),即使我在所有后来使用拒绝回调?

时间:2015-06-17 01:57:30

标签: javascript promise es6-promise rsvp-promise

我在最后放置了捕获,但它们至少在一个特定实例中返回空对象。对于任何不为人知的事情都是必要的,或者它只是让我搞砸了?

$( document).ready(function(){
    app.callAPI()//a chainable a RSVP wrapper around a jquery call, with its own success() fail() passing forward to the wrapper, so it will either be a resolved or rejected thenable to which is now going to be chained 
        .then(
            function(env) {
                //set the property you needed now
                app.someSpecialEnvObj = env;
            },
            function(rejectMessage){
                console.log('call.API() cant set some special env object..');
                console.log(rejectMessage);
            }
        )
        .catch(
        function(rejectMessage){
            if(rejectMessage){
                //a just incase, DOES IT HAVE VALUE, for somebody that may have not done their homework in the parent calls?
                console.log('you have some kind of legitimate error, maybe even in callAPI() that is not part of any problems inside them.  you may have forgotton handle something at an early state, your so lucky this is here!)
            } else {
                console.log('can this, and or will this ever run.  i.e., is there any value to it, when the necessity to already be logging is being handled in each and every then already, guaranteeing that we WONT be missing ANYTHING')
            }
        }
    );
});

是不是错了?或者是否有某种用途,即使我仍然在所有父链接的.then(resolve, reject)方法的所有用法中使用错误/拒绝处理程序?

编辑:我希望更好的代码示例。我想我可能仍然在命名中使用某种反模式,我rejectMessage在我的例如,它是jqXhr对象吗?

所以也许我应该正确地命名他们或者什么?即jqXhr?顺便说一句,我想在每个then()内部当场拒绝它的原因,如果有错误,是因为这样我可以大量记录每个单独的呼叫,如果那里有特定的问题,那样我没有必要跟踪任何事情。微记录,因为我可以。

Promise正在以这种方式帮助开放调试世界。

以下是我尝试过的三个例子。我更喜欢method1和method2,我决不会回到method3,这是我在promise地区开始的地方。

//method 1
app.rsvpAjax = function (){
    var async,
        promise = new window.RSVP.Promise(function(resolve, reject){
            async = $.extend( true, {},app.ajax, {
                success: function(returnData) {
                    resolve(returnData);
                },
                error: function(jqXhr, textStatus, errorThrown){
                    console.log('async error');
                    console.log({jqXhr:  jqXhr, textStatus: textStatus, errorThrown: errorThrown});
                    reject({ jqXhr: jqXhr, textStatus: textStatus, errorThrown: errorThrown}); //source of promise catch data believe
                }
            });
            $.ajax(async); //make the call using jquery's ajax, passing it our reconstructed object, each and every time
        });
    return promise;
};

app.callAPI = function () {
    var promise =app.rsvpAjax();
    if ( !app.ajax.url ) {
        console.log("need ajax url");
        promise.reject(); //throw (reject now)
    }
    return promise;
};

//method 2
app.ajaxPromise = function(){
    var  promise,  url = app.ajax.url;
    var coreObj = { //our XMLHttpRequestwrapper object
        ajax : function (method, url, args) {  // Method that performs the ajax request
            promise = window.RSVP.Promise( function (resolve, reject) {    // Creating a promise
                var client = new XMLHttpRequest(),  // Instantiates the XMLHttpRequest
                    uri = url;
                uri = url;
                if (args && (method === 'POST' || method === 'PUT')) {
                    uri += '?';
                    var argcount = 0;
                    for (var key in args) {
                        if (args.hasOwnProperty(key)) {
                            if (argcount++) {
                                uri += '&';
                            }
                            uri += encodeURIComponent(key) + '=' + encodeURIComponent(args[key]);
                        }
                    }
                }
                client.open(method, uri);
                client.send();
                client.onload = function () {
                    if (this.status == 200) {
                        resolve(this.response);   // Performs the function "resolve" when this.status is equal to 200
                    }
                    else {
                        reject(this.statusText); // Performs the function "reject" when this.status is different than 200
                    }
                };

                client.onerror = function () {
                    reject(this.statusText);
                };
            });
            return promise;   // Return the promise
        }
    };
    // Adapter pattern
    return {
        'get' : function(args) {
            return coreObj.ajax('GET', url, args);
        },
        'post' : function(args) {
            return coreObj.ajax('POST', url, args);
        },
        'put' : function(args) {
            return coreObj.ajax('PUT', url, args);
        },
        'delete' : function(args) {
            return coreObj.ajax('DELETE', url, args);
        }
    };
};

app.callAPI = function () {
    var async, callback;
    async =app.ajaxPromise() ; //app.ajaxPromise() is what creates the RSVP PROMISE HERE<
    if(app.ajax.type === 'GET'){async = async.get();}
    else if(app.ajax.type === 'POST') {async = async.post();}
    else if(app.ajax.type === 'PUT'){async = async.put();}
    else if(app.ajax.type === 'DELETE'){ async = async.delete();}
    callback = {
        success: function (data) {
            return JSON.parse(data);
        },
        error: function (reason) {
            console.log('something went wrong here');
            console.log(reason);
        }
    };
    async = async.then(callback.success)
        .catch(callback.error);
    return async;
};

//method 3 using old school jquery deferreds
app.callAPI = function () {
    //use $.Deferred instead of RSVP
    async = $.ajax( app.ajax) //run the ajax call now
        .then(
        function (asyncData) { //call has been completed, do something now
            return asyncData;  //modify data if needed, then return, sweet success
        },
        function(rejectMessage) {  //call failed miserably, log this thing
            console.log('Unexpected error inside the callApi.  There was a fail in the $.Deferred ajax call');
            return rejectMessage;
        }
    );
    return async;
};

我也将onready作为另一个备份运行。

window.RSVP.on('error', function(error) {
    window.console.assert(false, error);
    var response;
    if(error.jqXhr){
        response = error.jqXhr;
    } else {
        //response = error;
        response = 'is this working yet?';
    }
    console.log('rsvp_on_error_report')
    console.log(response);
});

编辑错误示例

//one weird error I can't understand, an empty string("")?
{
  "jqXhr": {
    "responseText": {
      "readyState": 0,
      "responseText": "",
      "status": 0,
      "statusText": "error"
    },
    "statusText": "error",
    "status": 0
  },
  "textStatus": "error",
  "errorThrown": "\"\""
}
//another wierd one, but this one comes from a different stream,  the RSVP.on('error') function
{
  "readyState": 0,
  "responseText": "",
  "status": 0,
  "statusText": "error"
}

3 个答案:

答案 0 :(得分:2)

  

我最后把抓到了

这是他们的典型位置 - 您处理链中某处发生的所有错误。重要的是不要忘记完全处理错误,最后建议采用全能的方法。

  

即使我在所有onreject来电中使用.then(…)处理程序?

这有点奇怪。通常所有错误都在一个中心位置处理(最后是catch),当然如果你想要,你可以在任何地方处理它们,然后继续链。

只需确保了解difference between an onreject handler in a then and in a catch,您就可以自由使用它们。尽管如此,建议最后catch来捕捉then回调本身的错误。

  

他们至少在一个特定的实例中返回空对象。

然后承诺搞砸了 - 它绝不应该没有理由拒绝。

似乎是造成的
if ( !app.ajax.url ) {
    console.log("need ajax url");
    promise.reject();
}
在您的代码中应该是

if (!app.ajax.url)
    return Promise.reject("need ajax url");
  

对于任何不为人知的事情都有必要吗?

不是真的。问题是catch通常是一个包罗万象,甚至捕获意外的例外。所以,如果你可以区分它们,你会对意想不到的事情做些什么?

通常你会为那些设置某种全局unhandled rejection handler,这样你就不必确保在每个保证链的末尾手动处理它们。

答案 1 :(得分:2)

我认为一般性问题在没有示例的情况下应该得到一个简单的答案。

迂腐的技术答案是'不',因为.catch(e)相当于.then(null, e)

然而 (这是一个很大的“然而”),除非你实际传入null,否则你将会传递可能在运行时失败的东西(比如编码错误),并且你需要一个后续的catch来捕获它,因为兄弟拒绝处理程序的设计不会抓住它:

.then(onSuccess, onFailure); // onFailure wont catch onSuccess failing!!

如果这是链的尾部,则onSuccess中的(甚至编码)错误将永远被吞噬。所以不要这样做。

所以真正的答案是肯定的,除非你要归还链条,在这种情况下没有。

所有链都应该终止,但是如果你的代码只是调用者在你的调用返回后会添加的更大链的一部分,则由调用者正确终止它(除非你的函数是为了设计的)永远不会失败。)

我遵循的规则是:所有链都必须退回或终止(使用catch)。

答案 2 :(得分:1)

如果我没记错的话,当你的承诺被拒绝时,catch会被触发。由于您附加了失败回调,除非您在失败或成功回调中调用拒绝功能,否则您的捕获将不会触发。 换句话说,catch块在你的方法中被捕获。