2014-10-22 3 views
2

Я использую JQuery's $.when и $.get, чтобы получить некоторые данные и сделать что-то с ним. Когда возникает ошибка при получении или что-то с ней, я хочу обработать эту ошибку и обрабатывать ее иначе в зависимости от того, какие данные я извлекал/на каком пути я ее извлекал.Получить дополнительную информацию из отказавшего запроса JQuery jqXHR

К сожалению, информация, которая была отправлена ​​$.when().fail(...), скудная и не включает эту информацию. Как я могу размахивать этой информацией из отложенного в не-хаки [1] способом?

$.when(get(path1), get(path2) 
    .done(function(parsed1, parsed2) { 
    // do something with this date 
    }).fail(function(jqXHR, statusTxt, errTxt) { 
    // do something depending on which path failed... 
    }); 

function get(path) { 
    var parser = U.parser(); 
    return $.get('/getter' + path) 
    .then(function(data) { 
     return parser(data); 
    }); 
} 

[1]: Конечно, я мог бы закрыть по всему пути и некоторые глобальные объекты, которые я хочу, чтобы справляться с неудачами с, и справиться с ней в .fail() на отсроченных что $.get возвращается. Я мог бы также отказаться от Отложенного, который не провалился, но каким-то образом обертывает неудачу, но это также очень хладнокровно.

+0

ли 'vcfPath' уникальный "путь"? – guest271314

+1

Ну, вы получите подробную информацию в 'statusTxt' и' errText', если возникла проблема с клиентской стороной или с запросом, но если была ошибка сервера, то, очевидно, эта информация не может быть легко получена через эти параметры. – Wold

+0

@ guest271314 да, это (отредактировано 'path'). – Isaac

ответ

3

Поскольку объект jqXHR является одной из вещей, переданных обратно в $.when(), похоже, вы можете поместить туда вещи, связанные с вашим запросом. Например, если путь, что вы хотите, вы можете сделать это:

function get(path) { 
    var parser = U.parser(); 
    var p = $.get('/getter' + vcfPath) 
    .then(function(data) { 
     return parser(data); 
    }); 
    p.myPath = path; 
    return p; 
} 

Затем в вашем $.when() обработчика, вы будете иметь объект jqXHR, который можно извлечь из параметров.

Примечание: $.when() отклоняет, как только любой запрос отклоняется. Если вы действительно хотите, чтобы все запросы продолжались, и вы хотите знать, когда все было заполнено (разрешено или отклонено), вы не можете использовать для этого $.when(). jQuery не предлагает эту функцию. Вы можете построить его самостоятельно или использовать внешнюю библиотеку, обещание, которое предлагает, что (я использую Bluebird, который имеет Promise.settle()

Вот рабочий пример:.

var data = { 
    json: JSON.stringify({ 
     text: 'some text', 
     array: [1, 2, 'three'], 
    }), 
    delay: 1 
} 


function runAjax(data, value) { 
    var p = $.ajax({ 
     url:"/echo/json/", 
     data:data, 
     type:"POST", 
    }); 
    // put something on the jqXHR object for retrieval later 
    p.myData = value; 
    return p;  
} 

function runAjaxFail(data, value) { 
    var p = $.ajax({ 
     url:"/echo/junk/", 
     data:data, 
     type:"POST", 
    }); 
    // put something on the jqXHR object for retrieval later 
    p.myData = value; 
    return p;  
} 

$.when(runAjax(data, "Hello"), runAjax(data, "GoodBye"), runAjaxFail(data, "My Fail Message")).then(function(r1, r2) { 
    // for each arg [0] is data, [1] is status, [2] is jqXHR object 
    log(r1[2].myData); // logs "Hello" 
    log(r2[2].myData); // logs "GoodBye" 
}, function(jqXHR, textStatus, errorThrown) { 
    // fail handler 
    log("fail: " + jqXHR.myData); 
}); 

Работа демо: http://jsfiddle.net/jfriend00/g8z353cz/


Вот еще один подход, который полностью поддерживается в мире обещаний. Это берет на себя решение обещания ajax, так что вы можете точно указать любые данные, которые вы хотите в нем. В этой конкретной реализации я решил всегда решать e и просто используйте данные в разрешенном значении, чтобы указать, какие вызовы ajax преуспели или не удались, но вы можете использовать отклонение со значением, если хотите. Это гарантированно будет распространяться все пути назад:

function get(path) { 
    var parser = U.parser(); 
    var d = $.Deferred(); 
    $.get('/getter' + path) 
     .then(function(data) { 
      d.resolve(parser(data)); 
     }, function(jqXHR) { 
      // error handler 
      d.resolve({path: path, jqXHR: jqXHR}); 
     }); 
    return d.promise(); 
} 

И вы можете увидеть этот вид реализации здесь: http://jsfiddle.net/jfriend00/c0u40gqh/

+0

Хмм, это, кажется, не работает для меня: это не добавляет атрибут 'myPath' к объекту jqXHR, который я получаю, когда происходит обратный вызов с ошибкой. – Isaac

+0

@Isaac - jQuery немного запутывает, как он передает аргументы '$ .when()' (он работает по-другому, если есть одно обещание против более чем одного обещания). Во всяком случае, вот рабочий пример того, как вы могли бы делать то, что я предлагал. – jfriend00

+0

Это не работает, однако, с '.fail()' (или если это так, я не вижу, как), в этом случае мне нужна дополнительная информация. – Isaac

0

Попробуйте

Примечание, останавливается на первом error, хотя может реализовать обходное решение для этого. Ниже в первую очередь для шаблона возможно пользовательских ошибок

var data = { 
    "path1" : function() { return {"path1" : [1,2,3]} }, 
    "path2" : function() { return {"path2" : [7, 8, 9] }}, 
    "path1Error" : function() { 
     console.log("path1 error") 
    }, 
    "path2Error" : function() { 
     console.log("path2 error") 
    } 
}; 

    $.ajaxSetup({ 
     beforeSend: function(jqXHR, settings) { 
     var path = JSON.parse(
      decodeURIComponent(settings.data.split("=")[1]) 
     ); 
      jqXHR.path = (path + "Error") in data 
      ? data[path + "Error"] 
      : path + "Error"; 
     } 
    }); 

$.when(get("path1"), get("path2")) 
    .done(function(parsed1, parsed2) { 
     //console.log(parsed1, parsed2) 
    // do something with this date 
    }) 
    .fail(function(jqXHR, statusTxt, errTxt) {  
     jqXHR.path() 
    // do something depending on which path failed... 
    }); 

function get(path) { 
    var parser = function (p) { return data[p]()}; 
    // `error` 
    return $.post("/echo/jsons/", {json:JSON.stringify([path]) }) 
    .then(function(data) { 
     return parser(data[0]); 
    }); 
} 

jsfiddle http://jsfiddle.net/guest271314/o3Lk73wg/