等待所有 firebase 调用使用 map 函数完成
Posted
技术标签:
【中文标题】等待所有 firebase 调用使用 map 函数完成【英文标题】:Waiting for all firebase call to finish with map function 【发布时间】:2019-06-28 16:25:59 【问题描述】:我正在获取我的用户数据,并且每个用户都会多次调用 map 函数。我想等到所有数据都被推送到数组中,然后再操作数据。我尝试使用 Promise.all() 但它没有用。 在继续之前如何等待此地图功能完成?
不用说,当在 Promise.all() 中打印时,数组 user_list_temp
是空的。
const phone_list_promise_1 = await arrWithKeys.map(async (users,i) =>
return firebase.database().ref(`/users/$users`)
.on('value', snapshot =>
user_list_temp.push(snapshot.val());
console.log(snapshot.val());
)
);
Promise.all(phone_list_promise_1).then( () => console.log(user_list_temp) )
我把代码改成了这个,但我仍然得到一个错误的输出
Promise.all(arrWithKeys.map(async (users,i) =>
const eventRef = db.ref(`users/$users`);
await eventRef.on('value', snapshot =>
const value = snapshot.val();
console.log(value);
phone_user_list[0][users].name = value.name;
phone_user_list[0][users].photo = value.photo;
)
console.log(phone_user_list[0]);
user_list_temp.push(phone_user_list[0]);
));
console.log(user_list_temp); //empty array
【问题讨论】:
【参考方案1】:如果我正确理解您的问题,您可能会考虑修改您的代码以使用常规的 for..of
循环,每个用户都有一个嵌套承诺,当该用户的快照/值可用时解析:
const user_list_temp = [];
/*
Use regular for..of loop to iterate values
*/
for(const user of arrWithKeys)
/*
Use await on a new promise object for this user that
resolves with snapshot value when value recieved for
user
*/
const user_list_item = await (new Promise((resolve) =>
firebase.database()
.ref(`/users/$users`)
.on('value', snapshot =>
/*
When value recieved, resolve the promise for
this user with val()
*/
resolve(snapshot.val());
);
));
/*
Add value for this user to the resulting user_list_item
*/
user_list_temp.push(user_list_item);
console.log(user_list_temp);
此代码假定封闭函数被定义为使用async
关键字的异步方法,看到await
关键字在for..of
循环中使用。希望对您有所帮助!
【讨论】:
【参考方案2】:async/await
可以与firebase 一起使用
这就是我通常制作Promise.all
的方式
const db = firebase.database();
let user_list_temp = await Promise.all(arrWithKeys.map(async (users,i) =>
const eventRef = db.ref(`users/$users`);
const snapshot = await eventref.once('value');
const value = snapshot.value();
return value;
)
);
这篇文章对Promise.all
和async/await
https://www.taniarascia.com/promise-all-with-async-await/的使用给出了相当好的解释
这是我将如何重构您的新代码 sn-p 以便您不会混淆 promises
和 async/await
let user_list_temp = await Promise.all(arrWithKeys.map(async (users,i) =>
const eventRef = db.ref(`users/$users`);
const snapshot= await eventRef.once('value');
const value = snapshot.val();
console.log(value);
phone_user_list[0][users].name = value.name; // should this be hardcoded as 0?
phone_user_list[0][users].photo = value.photo; // should this be hardcoded as 0?
console.log(phone_user_list[0]);
return phone_user_list[0]; // should this be hardcoded as 0?
)
);
console.log(user_list_temp);
这是一个使用 fetch 而不是 firebase 的简单示例:
async componentDidMount ()
let urls = [
'https://jsonplaceholder.typicode.com/todos/1',
'https://jsonplaceholder.typicode.com/todos/2',
'https://jsonplaceholder.typicode.com/todos/3',
'https://jsonplaceholder.typicode.com/todos/4'
];
let results = await Promise.all(urls.map(async url =>
const response = await fetch(url);
const json = await response.json();
return json;
));
alert(JSON.stringify(results))
【讨论】:
一定是很晚了。我再次对其进行了测试,但它并没有像我想象的那样工作......我已经更新了帖子。你知道为什么我仍然得到一个空数组吗? 你混合了promises
和async/await
你不应该在Promise.all
中同时使用这两种方法
我还错过了Promise.all
前面的await
我尝试了新的 firebase 选项,但没有成功。我将 .on 更改为 .once,它按我的意愿工作。你知道为什么吗?
使用 once() 从数据库中获取一次值,而使用 on() 会继续监听数据的变化,直到你调用 off()。来自这篇文章中的评论***.com/questions/47572171/…。 cmets 作者是 google 的一名工程师,从事 firebase 工作以上是关于等待所有 firebase 调用使用 map 函数完成的主要内容,如果未能解决你的问题,请参考以下文章
记录或调试 iOS 的 Firebase HttpMetric 跟踪调用(无需等待 12 小时)