1

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

$( 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)所有父链 then-ables 中的所有方法使用使用错误/拒绝处理程序?

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

所以也许我应该准确地命名它们或什么?即jqXhr?顺便说一句,我喜欢在每个内部当场拒绝它的原因then(),如果有错误,是因为这样我可以大量记录每个单独的呼叫,如果那里特别有问题,那我就没有追踪任何东西。微博,因为我可以。

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

这是我尝试过的三个示例。我更喜欢方法 1 和方法 2,我绝不会回到方法 3,这是我在应许之地开始的地方。

//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"
}
4

3 回答 3

3

我把渔获放在最后

这是他们的典型职位——您处理链中某处发生的所有错误。重要的是不要忘记处理错误,最后有一个全面的做法是推荐的做法。

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

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

只要确保了解a和 a 中的处理程序之间的区别onrejectthencatch,您就可以自由地使用它们。尽管如此,catch最终还是建议在then回调本身中捕获错误。

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

然后承诺搞砸了——它永远不应该无缘无故地拒绝。似乎是由于

if ( !app.ajax.url ) {
    console.log("need ajax url");
    promise.reject();
}

在你的代码中应该是

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

对于未知的事情,是否需要捕获?

并不真地。问题是这catch通常是一个包罗万象的,甚至捕捉到意外的异常。所以如果你能区分它们,你会如何处理那些意想不到的?

通常你会为它们设置某种全局未处理的拒绝处理程序,这样你就不必确保在每个 Promise 链的末尾手动处理它们。

于 2015-06-17T05:08:01.240 回答
2

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

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

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

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

如果这是一条链的尾部,那么(甚至是编码)中的错误都会onSuccess被永远吞噬。所以不要那样做。

所以真正的答案是肯定的,除非你要退回链条,在这种情况下不是。

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

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

于 2015-06-17T15:03:45.387 回答
1

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

于 2015-06-17T04:34:03.893 回答