Как сообщить о дополнительном отклонении из выполненного обещания Ajax

#jquery #typescript #promise

#jquery #typescript #обещание

Вопрос:

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

 _loadPanel(url: string, data?: any) : JQueryPromise<any>
{
    return $.ajax(
        {
            url: url,
            type: data ? "POST" : "GET",
            data: data
        }).done(function (html: string, textStatus: string)
        {
             // Some function that exracts required data
             var $panel = extractPanelData(html);
             if (!$panel.length)
             {
                 // How to cause a reject here???
             }
        });
}
 

Вы не можете этого сделать (ниже), поскольку обещание, возвращаемое из Ajax, является неизменяемым, и оно все равно пахнет неправильно:

 var promise = $.ajax({...}).done(function(...)
{ 
     promise.reject("Data failed promise");
});
 

Есть ли простой способ сделать это, который не требует добавления дополнительного $.Deferred() объекта или это единственный шаблон?

Попытки:

Я попробовал следующее, чтобы я мог изменить родительский Deferred объект, но он не будет компилироваться:

 var dfd = $.Deferred();
var promise = dfd.promise();
promise = promise.then($.ajax(
            {
                cache: false,
                url: url,
                type: data ? "POST" : "GET",
                data: data
            }).done(...));
 

Это позволит мне объединить Ajax обещание с Deferred обещанием

Supplied parameters do not match any signature of call target:Type '(value: {}) => {}' requires a call signature, but type 'JQueryXHR' lacks one.

Предложения?

Что-то классное:

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

например, передача начальных параметров $.ajax таким образом:

     $.when({
            url: url,
            type: data? "POST" : "GET",
            data: data
        }).then($.ajax).done(function (html: string, textStatus: string)
 

или отдельные параметры, подобные этому:

 $.when("Hello!", 22, "There!")
    .then(insertPanel);
 

Это может иметь интересные преимущества, если результат привязан к предыдущим обещаниям, поскольку вызов Ajax больше не выполняется немедленно, а только после завершения предыдущих шагов.

Комментарии:

1. если вы хотите отклонить, throw из then .

2. @Daniel A. White: Вы подразумеваете, что система исключений привязана к системе обещаний jQuery?

3. обещания jquery должны обрабатывать исключения

4. @Daniel A. White: У вас есть ссылка, поскольку я не нахожу ничего полезного (пока). Я не знал, что они обрабатывают исключения в асинхронных операциях.

5. вы могли бы использовать Q и обернуть им обещание jquery.

Ответ №1:

Здесь есть несколько особенностей:

  • .then связывает обещания и изменяет их состояние.
  • .done не связывает обещания, а добавляет обработчик к текущему обещанию и возвращает его.

Итак:

 var xhr = $.ajax({...});
p = xhr.then(function(data){
    // fail if check fails
    if(additionalChecksFail) return $.Deferred.reject(Error("Invalid Request").promise(); 
    return data; // otherwise we maintain the same data
});

p.then(function(data){
   // will only run if data validation passed.
});
 

Комментарии:

1. Я, хотя done и вернул исходное обещание, поскольку они действительно связаны (обычно с fail next).

2. @TrueBlueAussie да, он возвращает исходное обещание, он не связывает обещания (подумайте о реальной цепочке для этой аналогии :)).

3. Тогда я не понимаю, почему я не мог этого сделать .then($ajax().done()) , что и делала моя попытка (если вы игнорируете детали). Это должен быть тот же объект, .then($ajax()) который я считал действительным. Это просто сильная проблема с типизацией в Typescript?

4. @TrueBlueAussie $ajax возвращает обещание, в котором .then принимает функцию, которую вы можете сделать .then(function(res){ return $.ajax(..); }) , это похоже на то, как вы передаете функцию обратного вызова вместо ее прямого вызова.

5. Я использовал then для цепочки функций, которые возвращают обещания в тестах. jsfiddle.net/TrueBlueAussie/s8XmJ/1 Он выполняет обещания последовательно, связывает результаты для последующих then