在节点v 6.11.5上返回forEach中的promise

时间:2018-03-24 14:38:44

标签: javascript firebase promise es6-promise

我正在开发一个在Node v6.11.5上运行的Firebase云功能,所以我不能使用Async Await(据我所知)。一般的想法是我遍历对象,提取数据,在返回相关信息的不同服务器上ping API,然后将新信息添加到对象,然后再将其添加到数组并继续。

API返回信息,但不及时。如果我注销对象,则返回3个字段,但匹配为空。

当我应该使用Promise.all()时,这会是一个实例吗?如果是这样的话。我尝试将getMatches创建为一个promise,但该函数将继续运行。

...
const list = [];
...
return db.collection('users').get()
  .then((snapshot) => {
    return snapshot.forEach((doc) => {
      const user = doc.data();
      const obj = {};
      obj.id = user.id;
      obj.name = user.name;
      obj.matches = [];

      try {
        getMatches(user.param1, user.param2)
          .then(res => {
            obj.matches.push(res);
          })
      }
      catch (error) {
        console.log('error => ', error);
      }

      list.push(obj);
    });
  })
  .then(() => {
    ... sorts list ...
  })
  .then(() => {
    ... returns list to database ...
  });

const getMatches = function (param1, param2) {
  const url = 'https://something.herokuapp.com/callback.php';
  return axios.post(url, qs.stringify({
      data: param1,
      name: param2
    }))
    .then(res => {
      return res.data;
    })
    .catch(error => {
      console.log('ERROR => ', error);
    });
}

2 个答案:

答案 0 :(得分:0)

是的,在继续之前,使用Promise.all检查每个getMatches是否得到解析(并推送到列表中):

false

答案 1 :(得分:0)

QuerySnapshot中,而不是使用forEach方法。有一个属性调用docs来将结果作为数组获取,然后你可以map进入Promises数组。

参考:Firebase QuerySnapshot



db.collection('users').get()
  .then((querySnapshot) => {
    // 1. Get docs by properties `docs`
    const docs = querySnapshot.docs;
    
    // 2. Use map to convert array of doc into array of promise 
    const getMatchesPromises = docs.map(doc => {
      const user = doc.data();
      return getMatches(user.param1, user.param2)
        .then(res => {
          return {
            id: user.id,
            name: user.name,
            matches: [res],
          }
        });
    });
    
    // 3. Call Promise.all to execute array of promises, 
    // return the result so we can catch them in next then.
    return Promise.all(getMatchesPromises);
  })
  .then(list => {
    // ... your desired result from Promise.all
    /*
    list = [
      { id: 1, name: 'AAA', matches: [...] },
      { id: 2, name: 'BBB', matches: [...] },
    ];
    */
  });