在这种情况下如何回复承诺?

时间:2017-12-20 09:30:03

标签: javascript firebase firebase-realtime-database

我是使用JavaScript的Firebase新手,我知道我可以使用检索数据的输出返回一个promise。但在下列情况下,我无法真正看到它:

filterUsersAndCalculateMatches = (userProfile, userID, potentialMatches, maxDistanceToSearchForMatches) => {
   const TOTAL_SCORE = 100;
   var matches = {}; // Matches to be stored in the database
   potentialMatches.forEach(user => {
     if (user.val() !== userID) {

           databaseRef.child(`users/${user.val()}/profile`).once("value", (snapshot) => {
             const matchScore = calculateMatchScore(userProfile, snapshot.val(), maxDistanceToSearchForMatches);
             //console.log("final score is " + matchScore);
             if (matchScore) {
               const match = {
                   compatibility: matchScore / TOTAL_SCORE,
                   distance: distance,
                   profile: snapshot.val()
               }
               matches[user.val()] = match;
             }
           });
     }
   });
 };

我在迭代用户' ID和访问其配置文件以进行一些计算,并将结果及其配置文件添加到对象。

如何在所有用户完成后返回一个promise对象对象?

2 个答案:

答案 0 :(得分:1)

.once()返回一个承诺。 您可以使用Promise.all()。 Promise.all()获取一个promises数组作为参数,它返回一个promise,它将在所有传递的promises解析时解析。 修改后的代码如下所示:

filterUsersAndCalculateMatches = (userProfile, userID, potentialMatches, maxDistanceToSearchForMatches) => {
  var matches = {}; // Matches to be stored in the database
  const promisesList = [];
  potentialMatches.forEach(user => {
    if (user.val() !== userID) {
        // save a reference to the promise
        const dataPromise = databaseRef.child(`users/${user.val()}/profile`).once("value", (snapshot) => {
            // ...
          });
        // push the promise in the promise list
        promiseList.push(dataPromise);
    }
  });

  return Promise.all(promisesList).then(() => Promise.resolve(matches));
};

即使列表中的某个承诺被拒绝,您也可能希望解决。 您可以执行以下操作,处理被拒绝的承诺。

promiseList.push(
  // have to handle the reject
  dataPromise
    .then(data => data)
    // returns a resolved promise with { error } object.
    // doing this Promise.all() will always resolve even if some of them are rejected.
    .catch(error => {
      return { error: error };
    })
);

答案 1 :(得分:0)

您可以创建一个在完成配置文件迭代时使用matches对象解析的promise。注意我没有处理错误

filterUsersAndCalculateMatches = (userProfile, userID, potentialMatches, maxDistanceToSearchForMatches) => {
  //Return a new promise
  return new Promise((resolve, reject) => {
    const TOTAL_SCORE = 100;
    var matches = {}; // Matches to be stored in the database
    var promises = []; // create an array for promises during iteration over profiles
    potentialMatches.forEach(user => {
      if (user.val() !== userID) {
        // Save promise in var p
        var p = databaseRef.child(`users/${user.val()}/profile`).once("value").then((snapshot) => {
          const matchScore = calculateMatchScore(userProfile, snapshot.val(), maxDistanceToSearchForMatches);
          //console.log("final score is " + matchScore);
          if (matchScore) {
            const match = {
              compatibility: matchScore / TOTAL_SCORE,
              distance: distance,
              profile: snapshot.val()
            }
            matches[user.val()] = match;
          }
        });
        promises.push(p);
      }
    });

    Promise.all(promises).then(resolve.bind(resolve, matches));
  });
};