Обещания вызывают их успешный обратный вызов слишком поздно

#javascript #jquery #ajax #promise

#javascript #jquery #ajax #обещание

Вопрос:

У меня есть следующий код:

 products.SaveApplications = function (product) {
    var promises = [];

    ko.utils.arrayForEach(product.Applications(), function (item) {
       var applicationToSend = ko.mapping.toJS(item);
       promises.push($.ajax({
             type: "POST",
             contentType: "application/json",
             url: serviceUrl   "/InsertApplication",
             data: JSON.stringify(applicationToSend),
             success: function (data) {
                 alert("Doing success callback now.");
                 item.ID(data);
             }}));
    });

    return promises;
}
  

Затем функция products.SaveEnvironments , которая в основном такая же, за исключением того, что она вызывает другую функцию в моем контроллере, и функция products.SaveInstallations , которая, опять же, в основном такая же, за исключением того, что ей нужно ждать сохранения сред и приложений, потому что у нее есть некоторые зависимые данные (приложение.ИДЕНТИФИКАТОР и Environment.ID ).

Теперь у меня есть функция, которая вызывает обе эти функции и ждет их, пока обе не завершатся:

 products.SaveChanges = function (product) {
    // (...)
    var promises = products.SaveApplications(product);
    promises = promises.concat(products.SaveEnvironments(product));

    $.when(promises).done(function () {
       alert("we shouldn't see this before the other message!");
       products.SaveInstallations(product);
    }); 
};
  

Проблема в том, что окно предупреждения с надписью «Мы не должны видеть это сообщение перед другим сообщением!» на самом деле появляется перед «Выполнение успешного обратного вызова сейчас», что означает, что мои свойства ID на данный момент равны нулю. Это приводит меня к выводу, что $.when вызов выполняет только фактические обещания, но не ждет завершения успешных обратных вызовов. Как я могу заставить его ждать? Спасибо.

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

1. Попробуйте переключиться .success на .then there, это приведет к тому, что он вернет новое обещание, также — добавьте return data в конец его после изменения на .then

2. Спасибо за ваш комментарий, я ценю это. 🙂 К сожалению, он по-прежнему делает то же самое. 🙁

3. Можете ли вы изменить свой код в этом примере, чтобы он не использовался .postJSON , поскольку я с ним не знаком? Обычный $.ajax может облегчить обнаружение проблемы.

4. Извините за задержку, у меня был обеденный перерыв. Я соответствующим образом отредактировал сообщение.

5. Не используйте success: function(){ use .then

Ответ №1:

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

Вместо этого вам нужно использовать .apply для имитации вызова $.when с каждым обещанием в качестве отдельного аргумента, например:

 $.when.apply(null, promises).done(function () { ... });