使用 javascript 按顺序解决承诺/从内容丰富的 CMS 作出反应
resolving promises in a sequential order using javascript / react from contentful CMS
我正在尝试从内容丰富的 CMS 中按顺序获取一系列数据,完成后初始化我的 React 应用程序。我可以说我没有正确解决这些承诺,并且遇到了竞争条件,但我不确定如何解决这个问题。
鉴于以下情况:
this.contentfulClient.getEntry('4KGFPDFY2MZrRWCi4hZj2g')
.then((entry) => {
//console.log(entry);
dataStore.siteData = entry.fields;
})
.then(() => {
this.contentfulClient.getEntries({
content_type: 'visionsData'
})
.then((response) => {
let visionsArr = [];
response.items.map((vision) => {
return visionsArr.push(vision.fields);
});
dataStore.visionsData = visionsArr;
console.log('visions');
})
})
.then(() => {
this.contentfulClient.getEntries({
content_type: 'inspirationsData'
})
.then((response) => {
//console.log(response.items);
let inspirationsArr = [];
response.items.map((inspiration) => {
return inspirationsArr.push(inspiration.fields);
});
dataStore.inspirationsData = inspirationsArr;
console.log('inspirations');
})
.then(() => {
console.log('data loaded');
this.setState({
dataLoaded: true,
})
})
})
.catch(console.error)
我想确保我首先抓取条目 4KGF...
然后将其添加到数据存储,然后获取 visionsData
条目,然后将它们添加到数据存储,然后获取 inspirationsData
条目,然后将它们添加到数据存储,然后将我的应用程序的状态设置为 dataLoaded: true
作为最后一件事。设置该状态后,我应该呈现我的应用程序,如下所示:
render() {
const { dataLoaded } = this.state;
if (!dataLoaded) {
return (<div>LOADING</div>)
}
return (
<Router>
<div className="App">
<Route exact path="/" component={Home} />
<Route exact path="/inspiration" component={Inspiration} />
<Route exact path="/redesign" component={Redesign} />
<Route exact path="/visualize" component={Visualize} />
<Route exact path="/confirmation" component={Confirmation} />
<Reset />
</div>
</Router>
);
}
但实际情况是,有时数据集的一部分会先于其他部分呈现,例如 (inspirationsData
),因此 dataLoaded
将被设置为 true,即使 visionsData
尚未添加到数据存储中。我知道我可以将每个单独的 getEntries
调用嵌套在前一个 then((response))
调用中,但是我会得到我试图避免的那种嵌套承诺结构的金字塔。我该如何避免这种情况并正确构建我的承诺?
当其中的操作是异步的并且您希望链按顺序执行时,您需要 return 对 then()
的承诺。
没有 return
,或者当 return 不是 promise 时,then()
会立即解析,无论在其中调用什么异步操作
仅起始示例:
this.contentfulClient.getEntry('4KGFPDFY2MZrRWCi4hZj2g')
.then((entry) => {
//console.log(entry);
dataStore.siteData = entry.fields;
})
.then(() => {
return this.contentfulClient.getEntries({
//^^^^ return promise to next `then()`
我正在尝试从内容丰富的 CMS 中按顺序获取一系列数据,完成后初始化我的 React 应用程序。我可以说我没有正确解决这些承诺,并且遇到了竞争条件,但我不确定如何解决这个问题。
鉴于以下情况:
this.contentfulClient.getEntry('4KGFPDFY2MZrRWCi4hZj2g')
.then((entry) => {
//console.log(entry);
dataStore.siteData = entry.fields;
})
.then(() => {
this.contentfulClient.getEntries({
content_type: 'visionsData'
})
.then((response) => {
let visionsArr = [];
response.items.map((vision) => {
return visionsArr.push(vision.fields);
});
dataStore.visionsData = visionsArr;
console.log('visions');
})
})
.then(() => {
this.contentfulClient.getEntries({
content_type: 'inspirationsData'
})
.then((response) => {
//console.log(response.items);
let inspirationsArr = [];
response.items.map((inspiration) => {
return inspirationsArr.push(inspiration.fields);
});
dataStore.inspirationsData = inspirationsArr;
console.log('inspirations');
})
.then(() => {
console.log('data loaded');
this.setState({
dataLoaded: true,
})
})
})
.catch(console.error)
我想确保我首先抓取条目 4KGF...
然后将其添加到数据存储,然后获取 visionsData
条目,然后将它们添加到数据存储,然后获取 inspirationsData
条目,然后将它们添加到数据存储,然后将我的应用程序的状态设置为 dataLoaded: true
作为最后一件事。设置该状态后,我应该呈现我的应用程序,如下所示:
render() {
const { dataLoaded } = this.state;
if (!dataLoaded) {
return (<div>LOADING</div>)
}
return (
<Router>
<div className="App">
<Route exact path="/" component={Home} />
<Route exact path="/inspiration" component={Inspiration} />
<Route exact path="/redesign" component={Redesign} />
<Route exact path="/visualize" component={Visualize} />
<Route exact path="/confirmation" component={Confirmation} />
<Reset />
</div>
</Router>
);
}
但实际情况是,有时数据集的一部分会先于其他部分呈现,例如 (inspirationsData
),因此 dataLoaded
将被设置为 true,即使 visionsData
尚未添加到数据存储中。我知道我可以将每个单独的 getEntries
调用嵌套在前一个 then((response))
调用中,但是我会得到我试图避免的那种嵌套承诺结构的金字塔。我该如何避免这种情况并正确构建我的承诺?
当其中的操作是异步的并且您希望链按顺序执行时,您需要 return 对 then()
的承诺。
没有 return
,或者当 return 不是 promise 时,then()
会立即解析,无论在其中调用什么异步操作
仅起始示例:
this.contentfulClient.getEntry('4KGFPDFY2MZrRWCi4hZj2g')
.then((entry) => {
//console.log(entry);
dataStore.siteData = entry.fields;
})
.then(() => {
return this.contentfulClient.getEntries({
//^^^^ return promise to next `then()`