2013-05-23 2 views
2

У меня есть функция upload_image, которая загружает файл из формы и возвращает обещание, представляющее запрос ajax. Тем не менее, возможно, что пользователь еще не выбрал файл в этой форме, и в этом случае я не могу вернуть обещание, потому что не будет никакого запроса ajax. Однако код, вызывающий upload_image, ожидает обещание для запроса ajax, поэтому функции done() и fail() предполагают, что запрос ajax завершен или завершен. Итак, вопрос заключается в том, что должно возвращать upload_image, если предварительное условие пользователя, уже выбравшего файл, не удается?Обработка jQuery обещаний, которые могут быть сбой по нескольким причинам

Другими словами, что является наилучшей практикой для обработки неудачного обещания, которое может быть неудачным по разным причинам?

Я подумал о возвращении обещания, которое уже не выполнено, с строкой «Пожалуйста, выберите файл», а затем проверьте это в функции сбоя, но это кажется взломанным. Я также рассматривал возможность разделения валидации и представления ajax на две разные функции, но это слишком много накладных расходов для такой небольшой части функциональности.

upload_image().done(function(){ 
    // image uploaded succesfully 
}).fail(function(jqxhr){ 
    // error uploading OR image was not selected - what's the best way to handle this? 
}); 

// pseudocode 
function upload_image() { 
    if (!user_has_selected_a_file) { 
    // what to do here? maybe: 
    // return new $.Deferred().reject('Please select a file'); 
    } else { 
    return $.ajax(); 
    } 
} 
+0

Почему возвращение неудачного обещания кажется взломанным? Это кажется мне разумным. –

+0

Не это лучше, чем просто возврат неудачного обещания, но вы всегда можете вызвать 'abort()' на вызов ajax немедленно, если проверка не прошла, как в [** this fiddle **] (http://jsfiddle.net/3etZa /) – adeneo

+0

@RayNicholus кажется взломанным, потому что нет необходимости действительно использовать обещание, когда ничего не откладывается. Консенсус в том, что это путь. – mike

ответ

2

Простейший подход, вероятно, заключается в моделировании ошибки jqXHR таким образом, что обработчик ошибок должен быть только поверхностно осведомлен о том, является ли сбой подлинной ошибкой jqXHR или чем-то синтетическим.

Например:

function upload_image() { 
    if (!user_has_selected_a_file) { 
     return $.Deferred().reject({simulated:true}, 'Please select a file', 'No file selected').promise(); 
    } else { 
     return $.ajax(...); 
    } 
} 

Тогда, в своей простейшей форме, ответ сделал upload_image() может структурирована следующим образом:

upload_image().done(function(data, textStatus, jqXHR) { 
    // image uploaded succesfully 
}).fail(function(jqXHR, textStatus, errorThrown) { 
    //display textStatus and/or errorThrown as required 
}); 

Или, если вам нужно различать положительно между этими двумя типами сбой:

upload_image().done(function(data, textStatus, jqXHR) { 
    // image uploaded succesfully 
}).fail(function(jqXHR, textStatus, errorThrown) { 
    if(jqXHR.simulated) { 
     //display textStatus and/or errorThrown as required 
    } 
    else { 
     //handle the genuine jqXHR and/or display textStatus and/or errorThrown as required. 
    } 
}); 
+0

Спасибо, кажется, что возвращение отвергнутого по умолчанию Отложенного, как это, является консенсусом. – mike

+0

Да, возвращение готового отвергнутого обещания является вполне подходящим обходным решением для подобных ситуаций. –

0

Обращайтесь с ней в функции отказа. Вы должны вернуть deffered вызов для того, чтобы быть логическим вызов .done/.fail

0

Вы можете вручную создать Deferred object, не в состоянии сразу с .reject() или .rejectWith() и вернуть его из функции. Вы можете опционально передать в него аргументы, которые указывают на ошибку.

Любые отказоустойчивые вызовы, привязанные к уже пропущенному объекту с отсрочкой, будут выполняться немедленно.