目标是用另一个对象数组过滤一个对象数组。 每个阵列都来自不同的来源。
以下设置可能看起来很怪异,尽管由于某些未提及的原因而不幸地是必需的。
到目前为止,以下是我的解决方案。不幸的是,我无法顺次执行这些函数,因此特别是在调用filterJSON()之前,fetchJSONfiles()已完全完成。
我在这里呆了几个小时……任何帮助都将不胜感激,这将使我过得愉快。谢谢!
示例数据:
allposts: [
{
dateofpost: "1539181118111",
textid: "1",
userid: "Alice",
},
{
dateofpost: "1539181118222",
textid: "3",
userid: "Bob",
},
]
-
allfilteredTexts: [
{
title: "Lorem",
textid: "1",
},
{
title: "Ipsum",
textid: "2",
},
{
title: "Dolor",
textid: "3",
},
]
预期结果:
latestPosts: [
{
title: "Lorem",
textid: "1",
},
{
title: "Dolor",
textid: "3",
},
]
到目前为止,我的解决方案是
class Explore extends React.Component {
constructor(props) {
super(props);
this.state = {
allposts: [],
textids: [],
userids: [],
allfilteredTexts: [],
};
}
componentDidMount() {
const allfilteredTexts = {...this.state.allfilteredTexts}
firebase
.firestore()
.collection("allposts")
.orderBy("dateofpost")
.get()
.then(snapshot => {
const allposts = this.state.allposts;
snapshot.forEach(doc => {
allposts.push({
userid: doc.data().userid,
textid: doc.data().textid,
dateofpost: doc.data().dateofpost,
});
});
this.setState({
allposts: allposts,
});
})
.catch(function(error) {
console.log("Error getting documents: ", error);
})
.then(() => {
this.filterArrayIds();
})
.then(() => {
this.fetchJSONFiles();
})
.finally(() => {
this.filterJSON();
});
}
filterArrayIds() {
var userids = this.state.userids
var textids = this.state.textids
if (this.state.allposts) {
var filtereduserids = [...new Set([].concat(...this.state.allposts.map(o => o.userid)))];
var filteredtextids = [...new Set([].concat(...this.state.allposts.map(p => p.textid)))];
this.setState({
userids: filtereduserids,
textids: filteredtextids,
})
}
}
fetchJSONFiles() {
if (this.state.userids) {
this.state.userids.forEach((username) => {
var filteredTexts = []
const options = {username} //here would be more API options //
getFile(options)
.then((file) => {
filteredTexts = JSON.parse(file || '[]');
})
.then (() => {
Array.prototype.push.apply(filteredTexts, this.state.allfilteredTexts);
this.setState({
allfilteredTexts: filteredTexts,
})
})
}
}
filterJSON(){
let latestPosts = (this.state.allfilteredTexts.filter(
(el) => { return el.id.indexOf(this.state.textids) !== -1;
}));
}
render () {
return (
<div>
<Switch>
<Route
path='/explore/latest/'
render={(props) => <ExploreLatest {...props} allposts={this.state.allposts} allfilteredTexts={this.state.allfilteredTexts} />}
/>
</Switch>
</div>
)
}
}
export default Explore;
答案 0 :(得分:1)
我建议这样修改:
fetchJSONFiles() {
if (this.state.userids) {
return Promise.all(this.state.userids.map((username) => {
var filteredTexts = []
const options = {username} //here would be more API options //
return getFile(options)
.then((file) => {
filteredTexts = JSON.parse(file || '[]');
})
.then (() => {
Array.prototype.push.apply(filteredTexts, this.state.allfilteredTexts);
this.setState({
allfilteredTexts: filteredTexts,
})
}))
}
}
然后是几行:
.then(() => {
this.fetchJSONFiles();
})
可以成为:
.then(() => {
return this.fetchJSONFiles();
})
为什么?
fetchJSONFiles
在Promise链的其余部分之前未完成的原因是,Promise链不知道等待fetchJSONFiles
的结果。 fetchJSONFiles
进行异步调用,因此其余同步代码将继续执行。
但是,通过从fetchJSONFiles返回Promise,我们可以“等待”。这使用了Promise.all
功能,该功能基本上说:“ 创建一个诺言,当这个诺言数组中的每个诺言完成时,就完成”。
我们使用forEach
而不是map
,因为这使我们可以基于基本数组创建一个新数组,而不仅仅是循环遍历它。然后,我们不只是调用getFile
,而是返回Promise链。因此,我们从this.state.userids
创建了一个Promises数组,并从中创建了一个Promise,当使用Promise.all
完成所有提取操作后,Promise便会解决。
然后,将其返回到位于componentDidMount
中的初始Promise链中。这告诉链等待继续执行该Promise的结果(该Promise是this.fetchJSONFiles
的结果),然后继续执行,在这种情况下,这将涉及执行finally
回调。
现在,要考虑其他一些因素。即,如果fetchJSONFiles
调用之一发生错误怎么办?这是您必须考虑的事情,但是这些更改应该可以使您起床并奔向想要的位置。
答案 1 :(得分:0)
.catch(function(error) {
console.log("Error getting documents: ", error);
})
.then(() => {
this.filterArrayIds();
})
.then(() => {
this.fetchJSONFiles();
})
.finally(() => {
this.filterJSON();
});
当第一个承诺解决时,第一个.then()会被调用,第二个,第三个和.finally()也会被调用(无论您的承诺者是否解决,最终都会被调用)。他们都在期待解决的第一个诺言。
您需要执行的操作如下:
firebase
.get()
.then(snapshot => {
// stuff happening with snapshot
this.filterArrayIds().then(() => {
this.fetchJSONFiles().then(() => {
this.filterJSON();
});
});
});
您的方法filterArraysId(),fetchJSONFiles()将必须返回一个Promise,该Promise会在完成工作后解决;)