因此,在这种情况下,我需要构建一个对象,然后将一些项目注入到该对象中,然后进行API调用,并将API的响应注入到该对象中。它是一个复杂的对象,因此我们假设它没问题,但是无论如何,我认为我需要同步执行这三件事,并且使用array.forEach意味着它们异步运行。

我希望我的示例足够简单易懂,但基本上我会做三件事:


创建一个空的班级/教室数组
遍历类ID数组,并为每个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,如果我正确地安排了功能,也许我什至不需要同步执行。

最佳答案

使用基于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)返回值还是承诺,$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

关于javascript - 与$ q同步使用forEach,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36337960/

10-11 12:39
查看更多