从一个消防仓库文档中检索数据以查询另一个



Firestore集合中有两个文档。

我想查询一个文档以获取用户的车牌,并使用该车牌检索存储在另一个文档中的车辆数据。

这是我的代码:

function get_full_name_by_nplate(nplate){
var docRef = global_db.collection("customer_data").doc('web-app-vehicle-data');
docRef.get().then(function(doc) {
var data = doc.data();
given_name = data["vehicles"][nplate]["policy_holder_given_name"];
family_name = data["vehicles"][nplate]["policy_holder_family_name"];

console.log("given name: " + given_name); //this prints correctly! ==> "Jaime"

return given_name + " " + family_name;//this returns undefined
});
}
//load user data ////driving scores from backend
function loadUserData(user){
var nplate_list;
var docRef = global_db.collection("customer_data").doc('web-app-user-data');
docRef.get().then(function(doc) {
var data = doc.data();
user_data = data["users"][user.email];
nplate_list = user_data["number_plates"];

}).then(function(){
for(nplate of nplate_list){

get_full_name_by_nplate(nplate).then(full_name => {
console.log(full_name);//this prints undefined
});
}
});
}

我已经阅读了这个答案如何从firestore数据库返回值?我知道Firestore返回promise,所以在Firestore数据检索后我总是必须使用.then

虽然我可以将正确的given_name打印到控制台,但函数function get_full_name_by_nplate返回undefined

也许不起作用的是,我把一个承诺嵌套在另一个承诺中,但我不知道嵌套它们是否错误,也不知道如何在不嵌套的情况下实现。

更新

根据@kvetis的回答,我改进了代码,现在它可以工作了。然而,这仍然感觉不对,我不得不将nplate_list作为参数从一个.then()传递到下一个。。我不想想象如果我必须传递它5次,而且我仍然嵌套2个.then()语句,这也感觉不自然。

//load user data ////driving scores from backend
function loadUserData(user){

var docRef = global_db.collection("customer_data").doc('web-app-user-data');
docRef.get().then(function(doc) {
var data = doc.data();
global_user_data = data["users"][user.email];
//console.log(global_user_data["number_plates"]);
var user_name  = global_user_data["name"] + " " + global_user_data["surname"];
document.getElementById("welcome_div").innerHTML = user_name;
var nplate_list = global_user_data["number_plates"];

console.log("these are the nplates: " + nplate_list);

return nplate_list;
})

.then(function (nplate_list) {
var docRef = global_db
.collection("customer_data")
.doc("web-app-vehicle-data");

docRef.get().then(function(doc) {
global_vehicle_data = doc.data()["vehicles"];

var cust_dropdown = document.getElementById("cust-search-dropdown");
dropdown_content = "";

for(nplate of nplate_list){
//console.log(nplate);
var full_name = get_full_name_by_nplate(global_vehicle_data, nplate);
dropdown_content += "<div class="cust-dropdown-items"><a href="#" id="" + nplate + "" class="number-plate-links">" + nplate + " " + full_name + "</a></div>";
}

cust_dropdown.innerHTML = dropdown_content;
addListeners();

// If user has only 1 vehicle then pre-load it
if(nplate_list.length == 1){
select_customer_express(nplate_list[0]);
}
});
});
}

问题是,在所有承诺完成之前,您可能正在阅读dropdown_content。您必须等到get_full_name_by_nplate全部完成。

不幸的是,你的代码是这样写的,以至于你一遍又一遍地下载车辆数据。

最好的方法是将两个文档加载一个接一个地链接起来。否则,它将是缓慢和相当昂贵的,因为你得到的是每个文件的账单。

function get_full_name_by_nplate(data, nplate) {
given_name = data["vehicles"][nplate]["policy_holder_given_name"];
family_name = data["vehicles"][nplate]["policy_holder_family_name"];
return given_name + " " + family_name;

}
//load user data ////driving scores from backend
function loadUserData(user) {
var nplate_list;
var docRef = global_db.collection("customer_data").doc("web-app-user-data");
docRef
.get()
.then(function (doc) {
var data = doc.data();
user_data = data["users"][user.email];
nplate_list = user_data["number_plates"];
})
.then(function () {
var docRef = global_db
.collection("customer_data")
.doc("web-app-vehicle-data");
return docRef.get();
})
.then(function (doc)  { return doc.data()})
.then(function (vehicle_data) {
for (nplate of nplate_list) {
var full_name=  get_full_name_by_nplate(vehicle_data,nplate);
dropdown_content +=
'<div class="cust-dropdown-items"><a href="#" id="' +
nplate +
'" class="number-plate-links">' +
nplate +
" " +
full_name +
"</a></div>";

}
// now you do things with `dropdown_content`
});
}

最新更新