Javascript使用异步函数按值填充数组

时间:2018-02-20 20:04:37

标签: javascript arrays asynchronous

我正在尝试填充一个数组,数据通过promises来自异步调用。 但是,在一天结束时,我的数组最终为空,或者它的全部相同值。 (不知怎的,我认为它是通过引用填充,而不是通过值,即使我克隆它)

控制台输出显示4个不同版本的“v2”,但是“totalFriendResults”数组只有2个条目,两者都是相同的。

我从V2获得的值很好,问题在于填充totalFriendResutls。我在推送阵列时做错了吗?

有关为何发生这种情况的任何想法?

for(var count = 0; count< globalFriendsList.length; count++)
{
  inspectEachFriend(globalFriendsList[count]).then(function(v2)
  {
    console.log("this is v2",v2);
    var fix = new Object();
    fix = v2;
    var cloneMe = clone(v2);
    totalFriendResults.push(cloneMe)
  }
}

2 个答案:

答案 0 :(得分:0)

我通常使用Promise.all()来完成此类任务

Promise.all(globalFriendsList.map(function(friend) {
    return inspectEachFriend(friend).then(function(v2) {
        console.log("this is v2",v2);
        var fix = new Object();
        fix = v2;
        var cloneMe = clone(v2);
        return cloneMe;
 })).then(function(totalFriendResults) {
     console.log(totalFriendResults) //--> array of cloneMe objects (not sure why you dont just return v2 ?!?)
 });

这是一个演示:

    var globalFriendsList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    function inspectEachFriend(friend) {
        return new Promise(function(resolve, reject) {
            var time = Math.random() * 1000;
            setTimeout(function() {
                resolve({"friendId" : friend, "waited" : time});
            }, time);
        });
    };

    Promise.all(globalFriendsList.map(inspectEachFriend))
        .then(function(totalFriendResults) {
           console.log(totalFriendResults) //--> array of inspectEachFriend() resolved objects
        }).catch(function(error) {
           console.error(error);
        });

答案 1 :(得分:0)

你没有以正确的心态接近承诺。想想你的代码中发生了什么。在你的循环中,发生以下情况:

  1. 你的承诺
  2. 等到该承诺解决后再将其推入阵列
  3. 循环继续。
  4. 你的问题是存在的,因为你不能控制2和3完成的顺序(protip:3几乎总是先完成)。在你的承诺解决之前,你的循环将不断自我运行。您的承诺解决得更慢,i将成为i的所有承诺的最后一个值。所以这里有解决方法:

    1. 使用let count = 0代替var count = 0。这会修复您的范围问题,因为count将在每次迭代中作为唯一存在。
    2. 您无法逐个控制每个承诺。你启动承诺并让它开始运行,然后使用Promise.all`一次控制所有这些承诺
    3. 我执行诺言,然后将其推入数组。它正在运行并且是异步的。我遍历所有globalFriendsList,现在我的数组runningPromises是一个充满运行承诺的数组。然后那些运行promises我使用Promise.all来确保所有的promises已经解决,然后再转到下一行代码。

      在此示例中,我对您的代码进行了一些更改。

      &#13;
      &#13;
      let promise1 = () => new Promise(resolve => {
        setTimeout(() => resolve('promise1 resolved'), 5000)
      })
      
      let promise2 = () => new Promise(resolve => {
        setTimeout(() => resolve('promise2 resolved'), 500)
      })
      
      let globalFriendsList = [promise1, promise2]
      let runningPromises = []
      for (let i=0; i < globalFriendsList.length; i++) {
        let promise = globalFriendsList[i]()
        .then((v2)=> {
          return v2
        })
        runningPromises.push(promise)
      }
      
      Promise.all(runningPromises)
      .then((friendList) => {
        console.log(friendList)
      })
      &#13;
      &#13;
      &#13;