所以我遇到这样一种情况,我需要构建一个对象,然后将一些项目注入(inject)到该对象中,然后进行 API 调用并将 API 的响应注入(inject)到该对象中。这是一个复杂的对象,所以我们假设没问题,但无论如何,我认为我需要同步执行这 3 件事,使用 array.forEach
意味着它们异步运行。
我希望我的示例足够简单易懂,但基本上我做了 3 件事:
- 创建一个空的类(class)/教室数组
- 遍历类 ID 数组并为每个
Class
创建一个对象 - 遍历
Students
数组并将它们插入Class
对象中的students
数组 - 遍历
Options
数组并将它们放入Class
对象中的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,如果我正确安排我的功能,也许我什至不需要同步执行。
最佳答案
使用返回数组的基于 Promise 的 API
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();
})
})
}
要返回解析为数组的 promise ,请使用 $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)
返回一个值还是一个 promise,$q.when
都会返回一个 promise。
请注意 $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 .
关于javascript - 将 forEach 与 $q 同步使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36337960/