如何在for循环之后返回单个promise,其中循环内的数组的每个元素都执行多个异步调用

时间:2017-08-09 09:56:10

标签: javascript angularjs

我有一系列对象,我需要克隆不同的值。

在准备主要修改过的对象数组之后,我将从每个承诺中获得这些值,我将不得不保存它。所以我很多人都需要这个作为一个承诺。

我不知道该怎么做。

以下是克隆oldUser数据所需的示例。说旧用户的信用评分= 100;但对于新用户,系统会随机创建默认信用。

对于用户数组中的每个用户,很少有细节必须使用异步调用进行更新。 这是要求

function getUserCreditScore(user){
  var url = '/someurl';
  return $http.get(url).then(function(res){
    user.creditScore = (res.data) ? res.data : 0;
  });
}

function getUserRecomandations(user){
   var url = '/someurl';
  return $http.get(url).then(function(res){
   user.recommendation = (res.data) ? res.data : 'basic recommendation';
  });
}  

function getUserHelpInfo(user){
   var url = '/someurl';
  return $http.get(url).then(function(res){
   user.helpInfo = (res.data) ? res.data : 'Help Info';
  });
}  


function clone(){
  var newUsers = angular.copy(oldUsers);

  for (var i=0; i<newUsers.length; i++){
    newUsers[i].id = undefined;
    getUserCreditScore(newUsers[i]);
    getUserRecommendation(newUsers[i]);
    getUserHelpInfo(newUsers[i]);
  }

  var promises = _.map(newUsers, user => user.save());
  $q.all(promises).then(function (data) {
   console.log(data);
  }
}

2 个答案:

答案 0 :(得分:0)

你需要在getScreditScore

返回的Promise数组上使用Promise.all

类似

function getCreditScore(){
    var url = '/someurl';
    return $http.get(url).then(res => (res && res.data) ? res.data : res);
}

function clone(){
    var newUsers = angular.copy(oldUsers);

    Promise.all(
        newUsers.map(newUser => {
            newUser.id = undefined;
            return getCreditScore()
            .then(result => newUser.creditScore = result);
        })
    ).then(results => // results will be an array of values returned by the get in getCreditScore(newUser)
        Promise.all(newUsers.map(user => user.save()))
    ).then(data =>
        console.log(data); // this will be the result of all the user.save
    );
}

注意:newUser.creditScorenewUsers.map回调中的.then中设置 - (对原始回答的最小更改)

或者,将用户传递给getCreditScore

function getCreditScore(user){
    var url = '/someurl';
    return $http.get(url)
    .then(res => (res && res.data) ? res.data : res)
    .then(score => user.creditScore = score);
}

function clone(){
    var newUsers = angular.copy(oldUsers);

    Promise.all(
        newUsers.map(newUser => {
            newUser.id = undefined;
            return getCreditScore(newUser);
        })
    ).then(results => // results will be an array of values returned by the get in getCreditScore(newUser)
        Promise.all(newUsers.map(user => user.save()))
    ).then(data =>
        console.log(data); // this will be the result of all the user.save
    );
}
  

就个人而言,我会写代码

function getCreditScore(){
    var url = '/someurl';
    return $http.get(url).then(res => (res && res.data) ? res.data : res);
}

function clone(){
    var newUsers = angular.copy(oldUsers);

    Promise.all(
        newUsers.map(newUser => {
            newUser.id = undefined;
            return getCreditScore()
            .then(result => newUser.creditScore = result)
            .then(() => newUser.save())
            .then(() => newUser);
        })
    ).then(data =>
        console.log(data); // this will be the newUsers Array
    );
}

但是,假设你在运行user.save()之前不需要等待所有的$ http.get - 实际上这可能比{{1}更有效率(非常小)并且newUser.save将串联运行

答案 1 :(得分:0)

好的,我知道你的意思,你希望你的数组中的每个元素做一些异步的事情。

所以你可以使用map和Promise.all。这是我的代码:

const asyncFunction = (item, cb) => {
  setTimeout(() => {
    console.log(`done with ${item}`);
    cb();
  }, 1000);
}

let requests = [1, 2, 3].map((item) => {
  return new Promise((resolve) =>{
    asyncFunction(item, resolve);
  });
});

Promise.all(requests).then(() => console.log('done'));