#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 () { ... });