所以我有一种情况需要构建一个Object,然后将一些项注入到该Object中,然后进行API调用并将API的响应注入该Object。它是一个复杂的Object,所以我们只是假设没问题,但无论如何,我认为我需要同步执行这3个事情并使用array.forEach
意味着它们是异步运行的。
我希望我的例子很容易理解,但基本上我做了三件事:
Class
Students
数组并将其推入students
对象Class
数组
Options
数组并将其推入options
对象Class
数组
最后,我对每个班级都有类似的东西:
{
class_id: "abc123",
students: [{}, {}, {}],
options: [{}, {}, {}]
}
最后,这是我的代码:
// Create Array of Class Objects
var classes = [];
function processArray(array, func) {
return $q(function(resolve, reject) {
array.forEach(function(item, index) {
func(item);
if (index === (array.length - 1)) resolve();
})
})
}
// Create Courier Objects
processArray(classIds, function(id) {
classes.push({class_id: id, students: [], options: []});
}).then(function(response) {
// Inject Students into each Class
processArray(students, function(students) {
_.find(classes, {'class_id': student.class_id}).students.push(student);
}).then(function(response) {
// Inject classOptions into each Class
processArray(classOptions, function(classOption) {
_.find(classes, {'class_id': classOption.class_id}).classOptions.push(classOption);
}).then(function(response) {
// Print the classes
console.log(classes);
})
})
});
我已经创建了一个同步执行的功能,但我想知道是否有人能想到更多,更清洁,更有效的方法来实现上述目标。它似乎非常hacky,如果我正确安排我的功能,也许我甚至不需要同步它。
答案 0 :(得分:1)
您正在使用嵌套的承诺。这些很糟糕。承诺的一个主要优点是避免深度嵌套的“回调噩梦”。
使用此语法...
promise1.then(function(response1) {
// do something with response 1 (and possibly create promise2 here based on response1 if required)
return promise2
}).then(function(response2) {
// do something with response 2
return promise3
}).then(function(response3) {
// do something with response 3
// do something with promise 3???
}).catch(function(errorResponse) {
// will trigger this on a failure in any of the above blocks
// do something with error Response
});
答案 1 :(得分:1)
processArray
函数返回一个解析为null的promise。
//WRONG
//Returns a promise that resolves to null
//
function processArray(array, func) {
return $q(function(resolve, reject) {
array.forEach(function(item, index) {
func(item);
if (index === (array.length - 1)) resolve();
})
})
}
要返回解析为数组的承诺,请使用$q.all
。
//RIGHT
//Returns a promise that resolves to an array
//
function processArray(array, func) {
var promiseArray = [];
array.forEach(function(item, index) {
promiseArray.push($q.when(func(item));
});
return $q.all(promiseArray);
}
无论是func(item)
是返回值还是承诺,$q.when
都会返回一个承诺。
请注意$q.all
不具弹性。它将通过一系列值解决,或者在第一个错误时解决被拒绝的问题。
processArray(array, func)
.then( function onFulfilled(dataList) {
//resolves with an array
$scope.dataList = dataList;
}).catch( function onRejected(firstError) {
console.log(firstError);
});
有关详细信息,请参阅AngularJS $q Service API Reference。