我有一个从$ 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通过返回promise而失败......没有实际工作 inline 。
在下面的示例中,我不明白该函数在执行时如何立即返回promise。在循环完成之前,“return deferred.promise”会执行吗?不会强制函数首先执行循环然后返回语句吗?
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.");
}
});
}
浏览器的解释器是否评估函数返回的类型(在本例中为promise),并允许您调用该类型的方法(例如,成功,错误)传递将在执行延迟时执行的回调函数.resolve,deferred.reject等?
答案 0 :(得分:1)
不,因为您已经意识到您需要确保在任何实际工作完成之前返回承诺。因此,在返回承诺之前进行内联工作是行不通的。
基本上这个想法是有一个内联函数,它只创建一个延迟对象并从中返回promise,然后有一个执行实际工作的异步操作,并且可以通过一个闭包访问deffered对象并可以设置它一旦工作完成就解决了。
所以你可以拿你的例子来做这样的事情:
function doSomethingAsync() {
var deferred = $q.defer();
setTimeout(function() {
// do the actual work
deffered.resolve();
}, 500);
return deferred.promise;
}
doSomethingAsync().then(function() {
console.log('Promise Resolved! and work is done');
});
答案 1 :(得分:1)
"是否会延迟退货。#34;在循环完成之前执行?不会强制函数首先执行循环,然后是return语句吗?
是。循环是同步的。
我查看的每个示例都使用异步进程($ timeout或setTimeout)来模拟正在完成的工作。真正的工作呢?如果我有多个长时间运行的进程要并行运行怎么办?
JavaScript并不是并行运行的。真正繁重的工作通常涉及IO,无论如何都是异步。如果您正在使用JS本身进行繁重的处理(这可能不是最佳选择),您应该a)以较小的块分割工作,这些块以超时(异步)顺序运行,或者b)在单独的环境,即WebWorker,具有异步通信。
使用上面的模式会产生以下代码,但我无法想象它是否正常工作。这有用吗?
它会工作"但它不会异步运行,更不用说并行了。
浏览器的解释器是否评估函数返回的类型(在本例中为promise),并允许您调用该类型的方法(例如,成功,错误),传递回调函数在执行deferred.resolve,deferred.reject等时执行?
这里没有翻译魔法。 Promise是具有普通方法的普通对象,可以由用户libraries创建,并且通常的语义适用于它们。