2016-09-12 2 views
0

Как я могу ждать, пока цикл for перейдет в следующий цикл?узел обещание для цикла ждать результата

Как я могу убедиться, что userdetails выполняется, а realresult.playername присваивается новой переменной перед ее передачей?

код:

return new Promise(function (resolve, reject) { 

    arr = []; 


    messages.find({convid: convid}).then(function(result) { 

     for(var a in result) { 
      realresult = result[a]; 

      userData.userDetails(realresult.userid).then(function (result) { 
       realresult.playername = result.username; 
      }); 
      userData.usercashinfo(realresult.userid).then(function (resulttwo) { 
       realresult.playerdetails = resulttwo; 
      }); 

      arr.push(realresult); 

     } 

     return resolve(arr); 
    }); 
}); 
+0

использование 'Promise.all' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all –

+0

@Daniel_L я не знаю, как я мог бы переделать свою функцию, чтобы она работала с этим – maria

+0

Возможный дубликат [Javascript for loop Promises] (http://stackoverflow.com/questions/32701957/javascript-for-loop-promises) – Roberrrt

ответ

1

Вы пытаетесь написать обещание, что, когда он решает, возвращает массив разрешенных значений сулят. Здесь вы можете сделать две вещи:

  1. Используйте return, чтобы дождаться завершения обещания. В цепочке обещаний ничто фактически не разрешает ценность обещания, если это не return ред. (Вы также должны использовать это для message.find(), так как оно также дает вам обещание.)
  2. Постройте массив как массив обещаний, а не итераций и обещаний вдаваться в массив при их решении.
  3. Используйте Promise.all() для сбора объектов обещания - all() возвращается только после того, как все обещания, переданные ему, разрешились.
  4. (необязательно) Не ​​используйте повторно имя переменной result для обозначения нескольких вещей. Здесь не так, но это может вызвать ненужную путаницу.

Соединенный, это будет выглядеть примерно так:

return messages.find(...).then(function(result) { 
    var promiseArr = []; 
    for (var a in result) { 
    promiseArr.push(
     promise.all([userData.userDetails(...), userData.usercashinfo(...)]) 
     .then(function(detailinfo) { 
     var realresult = result[a]; 
     var details = detailinfo[0]; 
     var cashinfo = detailinfo[1]; 
     realresult.playername = details.username; 
     realresult.playerdetails = cashinfo; 
     return realresult; 
    }); 
    } 
    return Promise.all(promiseArr); 
}); 
+0

эй @yoz, я обновил свой пост, не могли бы вы внести некоторые изменения, чтобы сделать эту работу? – maria

+0

@maria конечно, я обновил здесь образец кода. – yoz

0

, так что я подумал, что это хорошая идея, пытаясь решить ее с помощью комбинации генераторов и обещаний, я не уверен, что его лучший путь, но это хорошая практика для комбинации двух, поэтому я попробовал.

Идея состоит в том, что функция генератора ожидает функцию обратного вызова перед началом новой итерации, и функция обратного вызова ожидает выполнения обоих обещаний, прежде чем сообщать функции генератора продолжить итерацию.

here is a more simple example that I first tried on codepen

return new Promise(function (resolve, reject) { 
    arr = []; 
    messages.find({convid: convid}).then(function(result) { 
     function* iterations() { 
      for (var i = 0; i < result.length; i++) { 
       realresult = result[i]; 
       try { 
        var cbResult = yield cb(result[i].userid); 
        realresult.playername = cbResult.playername; 
        realresult.playerdetails = cbResult.playerdetails; 
        arr.push(realresult); 
       } catch (e) { reject(e) } 
      } 
      return arr.value; 
     } 

     var it = iterations(); 
     it.next(); 

     function cb(userid) { 
      Promise.all([ 
         userData.userDetails(userid), 
         userData.usercashinfo(userid) 
         ]).then(
          function(values) { 
           var realresult = {playername : values[0], playerdetails : values[1]} 
           returnValue = it.next(realresult); 
           if (returnValue.done) { 
            resolve(returnValue); 
           } 
          }, 
          function(e) { reject(e) } 
         ); 
     } 
    }); 
}); 
+1

Избегайте антипаттера конструктора '' Promise' (http://stackoverflow.com/q/23803743/1048572)! – Bergi

+0

Этот код довольно запутан и не содержит ошибок. Вместо использования генераторов вам нужно просто перейти на 'async' /' await'. – Bergi

+0

http://prntscr.com/ch6i49 Я сделал то, что вы сделали @naortor, но тогда он не вернет массив в простой ответ? как [0] и [1]? – maria

Смежные вопросы