2017-05-26 75 views
0

我試圖從Firebase數據庫條目中獲取數據。用例如下:我將查詢具有緯度,經度和半徑的Web API,其中使用GeoQuery庫進行查詢,該庫提供與數據庫輸入項關聯的數據庫結構。我使用key_entered事件管理器來觸發所有匹配的位置數據庫條目。只讀一次Firebase數據庫條目並返回其值

我現在想檢查關聯的數據時間戳是否比現在更新,但我得到了一些掙扎,使數據超出了Promise。我知道下面的代碼由於Promises的異步性質而不起作用,但是有沒有可能將一次數據與一個變量相關聯,例如,等待Promise返回一些東西直到繼續(如等待等)?

我完全瞭解node.js的異步性質,但我必須將數據返回到res.send,因爲它提供了一個封閉的API調用。

我也已經使用回調函數來調用數據庫查詢承諾,並試圖將其關聯到數據,這並沒有工作。

function queryGeoLocation(req, res) { 
try { 
    const lat = parseFloat(req.params.lat); 
    const long = parseFloat(req.params.long); 
    const radius = parseFloat(req.params.radius); 

    let geoQuery = geoFire.query({center: [lat, long], radius: radius}); 

    data = new QueryData(); //Use this to handle data asynchronously 
    geoQuery.on("key_entered", (key, loc, dist) => { 
     isFutureEvent = false; 
     admin.database().ref("/events/").child(key).once("value").then((snapshot) => { 
      if(Date.parse(snapshot.val().date) >= Date.now()) 
       isFutureEvent = true; 
     }).catch(() => { 
     }); 
     console.log(isFutureEvent); 

     if (isFutureEvent){ 
      data.add(key, loc, dist); 
     } 
    }); 

    // When ready directly cancel the query provider and return data (since we only want to read once) 
    geoQuery.on('ready',() => { 
     geoQuery.cancel(); 
     res.send(data.getData()); 
    }); 
} catch (err) { 
    res.status(500).send("Error: " + err); 
} 

}

+0

真的,你應該在這裏做的是讓queryGeoLocation返回一個承諾,解決與調用者需要的數據。調用者比使用那個承諾,通過使用那個承諾的then()來回應數據的可用性。 –

+0

是的,這對我來說是一個很好的方式。我沒有意識到我可以在http請求中返回一個Promise。是否有可能通過XMLHttpRequest處理這種返回,我目前在客戶端使用該返回? – domna

+0

有一個名爲request-promise的node.js模塊,它返回一個在HTTP請求完成時解析的promise:https://www.npmjs.com/package/request-promise –

回答

0

我通過鏈接承諾了它自己。也許有點過於複雜,但我正在努力。

function queryGeoLocation(req, res) { 
    try { 
     const lat = parseFloat(req.params.lat); 
     const long = parseFloat(req.params.long); 
     const radius = parseFloat(req.params.radius); 

     let geoQuery = geoFire.query({center: [lat, long], radius: radius}); 

     getGeoData = function(geoQuery) { 
      return new Promise(function (resolve, reject) { 
       data = new QueryData(); 
       geoQuery.on("key_entered", (key, loc, dist) => { 
        data.add(key, loc, dist); 
       }); 

       geoQuery.on('ready',() => { 
        geoQuery.cancel(); 
        resolve(data.getData()); 
       }); 
      }); 
     }; 

     dbQuery = function (key) { 
      return new Promise(function(resolve, reject) { 
       admin.database().ref("/events/").child(key).on('value', (data) => { 
        if (Date.parse(data.val().date) < Date.now()) 
         resolve(false); 
        else 
         resolve(true); 
       }); 
      }); 
     }; 

     checkIfDateIsNewer = function(geoData) { 
      return new Promise(function (resolve, reject) { 
       for (let key in geoData){ 
        if(geoData.hasOwnProperty(key)) { 
         dbQuery(key).then((isNewer) => { 
          if (!isNewer) 
           delete geoData[key]; 
         }); 
        } 
       } 

       resolve(geoData); 
      }); 
     }; 

     getGeoData(geoQuery).then(checkIfDateIsNewer).then(function(data) { 
      res.send(data); 
     }).catch((err) => { 
      res.status(500).send("Error: " + err); 
     }); 
    } catch (err) { 
     res.status(500).send("Error: " + err); 
    } 
}