У меня есть массив объектов, возвращаемых из $http.get, для которых мне нужно выполнить три разных автономных почтовых процесса. Я считаю, что могу использовать $q.all для параллельного выполнения почтовых процессов.
Я вижу массу примеров, использующих $timeout/setTimeout, которые следуют этому шаблону:
function doSomethingAsync() {
var deferred = $q.defer();
setTimeout(function() {
deferred.resolve('hello world');
}, 500);
return deferred.promise;
}
doSomethingAsync().then(function(val) {
console.log('Promise Resolved!', val);
});
Я новичок в javascript, но это не суть моей проблемы. Функции $timeout и setTimeout уже являются асинхронными, и поэтому doSomethingAsync просто не возвращает обещание... фактическая работа не выполнялась inline.
В следующем примере я не понимаю, как функция возвращает обещание сразу после выполнения. Будет ли «return deferred.promise» выполняться до завершения цикла? Не будет ли функция вынуждена сначала выполнять цикл, а затем оператор return?
function doSomethingRealWorkAsync() {
var deferred = $q.defer();
//loop through the items in an array and perform some heavy lifting that will take time
deferred.resolve('Done!');
return deferred.promise;
}
doSomethingRealWorkAsync().then(function(val) {
console.log('Promise Resolved!', val);
});
В каждом рассмотренном мной примере используется асинхронный процесс (либо $timeout, либо setTimeout) для имитации выполняемой работы. А реальная работа? Что делать, если у меня есть несколько длительных процессов, которые я хочу запустить параллельно?
Использование приведенного выше шаблона даст следующий код, но я не могу представить, чтобы он работал правильно. Будет ли это работать? Если нет, то почему? Если да, то как?
$scope.items = [{}];
$scope.initialized = false;
function doOneThingToItemsAsync() {
var deferred = $q.defer();
for (var i in items) {
items[i].propertyA = 'this';
}
deferred.resolve('Done with One Thing!');
return deferred.promise;
}
function doAnotherThingToItemsAsync() {
var deferred = $q.defer();
for (var i in items) {
items[i].propertyB = 'that';
}
deferred.resolve('Done with Another Thing!');
return deferred.promise;
}
function doYetAnotherThingToItemsAsync() {
var deferred = $q.defer();
for (var i in items) {
items[i].propertyC = 'I smell a cat';
}
deferred.resolve('Done with Yet Another Thing!');
return deferred.promise;
}
function getItems () {
$http.get("/api/widgets", { timeout: 0 })
.success(function (data) {
items = data.items;
$q.all([doOneThingToItemsAsync(),
doAnotherThingToItemsAsync(),
doYetAnotherThingToItemsAsync()])
.then(function(result) {
for (var i in result) {
console.log(result[i]);
}
initialized = true;
});
})
.error(function (data) {
if (data.errorMessage) {
console.log("There was a problem retrieving your data: \n" + data.errorMessage + "\nPlease try again.");
} else {
console.log("There was a problem retrieving your data. Please try again.");
}
});
}
Оценивает ли интерпретатор браузера тип, возвращаемый функцией (в данном случае обещание), и позволяет ли вам вызывать методы для этого типа (например, затем, успех, ошибка), передавая функции обратного вызова, которые будут выполняться при выполнении deferred.resolve, deferred.reject и т.д.?