如何重构瀑布 .then()
how to refactor waterfall .then()
这里的代码使用动作加载数据,应该是系列的,但是很难编辑这段代码添加另一个 API 加载,语法不清晰。
this.props.loadNutMatrixes({perPage:'all'}).then(()=>{
this.props.loadIngredients().then(()=>{
this.props.getBadge().then(()=>{
this.props.loadNutInfoItems({perPage:'all'}).then(()=>{
this.props.getItemSize().then(()=>{
this.props.getSingleMenuCategory(this.props.category_uid).then(()=>{
this.props.loadAllStores(({per_page:'all'})).then(()=>{
if (this.props.selectedMenuItem ){
initialize("addNewMenuItem", {
...this.props.selectedMenuItem
})
}
})
})
})
})
})
})
})
Return 将其链接到外部承诺的承诺。
this.props.loadNutMatrixes({perPage:'all'}).then(()=>{
return this.props.loadIngredients()
})
.then(()=>{
return this.props.getBadge()
})
.then(()=>{
return this.props.loadNutInfoItems({perPage:'all'})
})
.then(()=>{
return this.props.getItemSize()
})
.then(()=>{
return this.props.getSingleMenuCategory(this.props.category_uid)
});
...
您可以通过链接 promise 而不是嵌套将其转换为垂直结构:
this.props.loadNutMatrixes({perPage:'all'})
.then(() => this.props.loadIngredients())
.then(() => this.props.getBadge())
.then(() => this.props.loadNutInfoItems({perPage:'all'}))
.then(() => this.props.getItemSize())
.then(() => this.props.getSingleMenuCategory(this.props.category_uid))
.then(() => this.props.loadAllStores(({per_page:'all'})))
.then(() => {
if (this.props.selectedMenuItem) {
initialize("addNewMenuItem", {
...this.props.selectedMenuItem
})
}
});
一个可能的改进是将所有接收参数的创建承诺的函数包装到不带参数的函数中,并将它们作为 props
传递:
loadAllNutMatrixes() {
return this.loadNutMatrixes({ perPage: 'all' });
}
loadAllNutInfoItems() {
return this.loadNutInfoItems({ perPage: 'all' });
}
getSingleMenuCategoryFromId() {
return this.getSingleMenuCategory(this.category_uid);
}
loadEveryStory() {
return this.loadAllStores({ perPage: 'all' });
}
那么你可以将最后一步重构到它自己的方法中:
onChainFinished() {
if (this.props.selectedMenuItem) {
initialize("addNewMenuItem", {
...this.props.selectedMenuItem
})
}
}
并将两者结合一些解构以实现更清洁的链:
const { props } = this;
props.loadAllNutMatrixes()
.then(props.loadIngredients)
.then(props.getBadge)
.then(props.loadAllNutInfoItems)
.then(props.getItemSize)
.then(props.getSingleMenuCategoryFromId)
.then(props.loadEveryStore)
.then(this.onChainFinished);
编辑 根据您的评论
using something like promise.all but in series way !
没有用于链接 Promises 的本机方法,但您可以构建适合您的用例的辅助方法来执行此操作。这是一个一般示例:
// `cp` is a function that creates a promise and
// `args` is an array of arguments to pass into `cp`
chainPromises([
{ cp: this.props.loadNutMatrixes, args: [{perPage:'all'}] },
{ cp: this.props.loadIngredients },
{ cp: this.props.getBadge },
{ cp: this.props.loadNutInfoItems, args: [{perPage:'all'}] },
{ cp: this.props.getItemSize },
{ cp: this.props.getSingleMenuCategory, args: [this.props.category_uid] },
{ cp: this.props.loadAllStores, args: [{per_page:'all'}] }
]).then(() => {
if (this.props.selectedMenuItem) {
initialize("addNewMenuItem", {
...this.props.selectedMenuItem
})
}
});
function chainPromises(promises) {
return promises.reduce(
(chain, { cp, args = [] }) => {
// append the promise creating function to the chain
return chain.then(() => cp(...args));
}, Promise.resolve() // start the promise chain from a resolved promise
);
}
如果您使用与上述相同的方法来重构带参数的方法,它也会清理此代码:
const { props } = this;
chainPropsPromises([
props.loadAllNutMatrixes,
props.loadIngredients,
props.getBadge,
props.loadAllNutInfoItems,
props.getItemSize,
props.getSingleMenuCategoryFromId,
props.loadEveryStory
])
.then(this.onChainFinished);
function chainPropsPromises(promises) {
return promises.reduce(
(chain, propsFunc) => (
chain.then(() => propsFunc());
), Promise.resolve()
);
}
如果 promise 不相互依赖,我会使用 Promise.all
:
const {props} = this;
Promise.all([
props.loadNutMatrixes({perPage: 'all'}),
props.loadIngredients(),
props.getBadge(),
props.loadNutInfoItems({perPage: 'all'}),
props.getItemSize(),
props.getSingleMenuCategory(props.category_uid),
props.loadAllStores(({per_page: 'all'})),
]).then(() => {
if (props.selectedMenuItem) initialize("addNewMenuItem", {...props.selectedMenuItem});
});
这里的代码使用动作加载数据,应该是系列的,但是很难编辑这段代码添加另一个 API 加载,语法不清晰。
this.props.loadNutMatrixes({perPage:'all'}).then(()=>{
this.props.loadIngredients().then(()=>{
this.props.getBadge().then(()=>{
this.props.loadNutInfoItems({perPage:'all'}).then(()=>{
this.props.getItemSize().then(()=>{
this.props.getSingleMenuCategory(this.props.category_uid).then(()=>{
this.props.loadAllStores(({per_page:'all'})).then(()=>{
if (this.props.selectedMenuItem ){
initialize("addNewMenuItem", {
...this.props.selectedMenuItem
})
}
})
})
})
})
})
})
})
Return 将其链接到外部承诺的承诺。
this.props.loadNutMatrixes({perPage:'all'}).then(()=>{
return this.props.loadIngredients()
})
.then(()=>{
return this.props.getBadge()
})
.then(()=>{
return this.props.loadNutInfoItems({perPage:'all'})
})
.then(()=>{
return this.props.getItemSize()
})
.then(()=>{
return this.props.getSingleMenuCategory(this.props.category_uid)
});
...
您可以通过链接 promise 而不是嵌套将其转换为垂直结构:
this.props.loadNutMatrixes({perPage:'all'})
.then(() => this.props.loadIngredients())
.then(() => this.props.getBadge())
.then(() => this.props.loadNutInfoItems({perPage:'all'}))
.then(() => this.props.getItemSize())
.then(() => this.props.getSingleMenuCategory(this.props.category_uid))
.then(() => this.props.loadAllStores(({per_page:'all'})))
.then(() => {
if (this.props.selectedMenuItem) {
initialize("addNewMenuItem", {
...this.props.selectedMenuItem
})
}
});
一个可能的改进是将所有接收参数的创建承诺的函数包装到不带参数的函数中,并将它们作为 props
传递:
loadAllNutMatrixes() {
return this.loadNutMatrixes({ perPage: 'all' });
}
loadAllNutInfoItems() {
return this.loadNutInfoItems({ perPage: 'all' });
}
getSingleMenuCategoryFromId() {
return this.getSingleMenuCategory(this.category_uid);
}
loadEveryStory() {
return this.loadAllStores({ perPage: 'all' });
}
那么你可以将最后一步重构到它自己的方法中:
onChainFinished() {
if (this.props.selectedMenuItem) {
initialize("addNewMenuItem", {
...this.props.selectedMenuItem
})
}
}
并将两者结合一些解构以实现更清洁的链:
const { props } = this;
props.loadAllNutMatrixes()
.then(props.loadIngredients)
.then(props.getBadge)
.then(props.loadAllNutInfoItems)
.then(props.getItemSize)
.then(props.getSingleMenuCategoryFromId)
.then(props.loadEveryStore)
.then(this.onChainFinished);
编辑 根据您的评论
using something like promise.all but in series way !
没有用于链接 Promises 的本机方法,但您可以构建适合您的用例的辅助方法来执行此操作。这是一个一般示例:
// `cp` is a function that creates a promise and
// `args` is an array of arguments to pass into `cp`
chainPromises([
{ cp: this.props.loadNutMatrixes, args: [{perPage:'all'}] },
{ cp: this.props.loadIngredients },
{ cp: this.props.getBadge },
{ cp: this.props.loadNutInfoItems, args: [{perPage:'all'}] },
{ cp: this.props.getItemSize },
{ cp: this.props.getSingleMenuCategory, args: [this.props.category_uid] },
{ cp: this.props.loadAllStores, args: [{per_page:'all'}] }
]).then(() => {
if (this.props.selectedMenuItem) {
initialize("addNewMenuItem", {
...this.props.selectedMenuItem
})
}
});
function chainPromises(promises) {
return promises.reduce(
(chain, { cp, args = [] }) => {
// append the promise creating function to the chain
return chain.then(() => cp(...args));
}, Promise.resolve() // start the promise chain from a resolved promise
);
}
如果您使用与上述相同的方法来重构带参数的方法,它也会清理此代码:
const { props } = this;
chainPropsPromises([
props.loadAllNutMatrixes,
props.loadIngredients,
props.getBadge,
props.loadAllNutInfoItems,
props.getItemSize,
props.getSingleMenuCategoryFromId,
props.loadEveryStory
])
.then(this.onChainFinished);
function chainPropsPromises(promises) {
return promises.reduce(
(chain, propsFunc) => (
chain.then(() => propsFunc());
), Promise.resolve()
);
}
如果 promise 不相互依赖,我会使用 Promise.all
:
const {props} = this;
Promise.all([
props.loadNutMatrixes({perPage: 'all'}),
props.loadIngredients(),
props.getBadge(),
props.loadNutInfoItems({perPage: 'all'}),
props.getItemSize(),
props.getSingleMenuCategory(props.category_uid),
props.loadAllStores(({per_page: 'all'})),
]).then(() => {
if (props.selectedMenuItem) initialize("addNewMenuItem", {...props.selectedMenuItem});
});