我有一些包含在promise
中的代码。此代码用于编辑远程数据库中的某些记录,并返回编辑记录的数量。如果编辑记录的数量大于0
(即已经完成了一些工作),那么我想一次又一次地运行相同的方法,直到我得到0
为止(即,没有更多的记录需要编辑)。
我尝试了一些不同的方法,但它们都没有终止(即没有调用解析)或者它们无法正常运行。
我试过第一个版本:
const doEdits = () => {
return new Promise((resolve, reject) => {
someDB.performEdits()
.then(count => {
if (count > 0) {
doEdits()
} else {
resolve()
}
})
.catch(reject)
})
}
return new Promise((resolve, reject) => {
someDB.init()
.then(doEdits)
.catch(reject)
})
我试过的第二个版本:
const doEdits = () => {
return new Promise((resolve, reject) => {
someDB.performEdits()
.then(count => {
resolve(count)
})
.catch(reject)
})
}
return new Promise((resolve, reject) => {
someDB.init()
.then(doEdits)
.then(count => {
if (count > 0 ) {
return doEdits() // 'doEdits()' did not work...
} else {
resolve()
}
})
.catch(reject)
})
欢迎提出任何建议。
答案 0 :(得分:3)
是的,您从未在resolve
分支中调用if
。但是你不应该在这里使用resolve
函数,避免使用Promise
constructor antipattern!只是做
function doEdits() {
return someDB.performEdits().then(count => {
if (count > 0) {
return doEdits();
} else {
return undefined; // ???
}
});
}
return someDB.init().then(doEdits);
答案 1 :(得分:1)
不要制作意大利面
你真的不需要创建一堆承诺,特别是因为你正在使用的底层库已经给你一个承诺。这种方法应该完成你的目标,而不需要额外的补充:
const doEdits = count => {
if(count > 0) {
return someDB.performEdits().then(doEdits);
}
};
return someDB.init()
.then(() => {
performEdits().then(doEdits)
});
这会将后续db调用的promise转换为第一个promise。任何后续的then
s(和catch
es将对返回的promise做出操作(即,等待它解析或拒绝),在传递给promise之前,它可能会被新的promise替换。它们。
为什么您的代码不起作用
一旦你决定要实例化Promise,你就承担了处理决心和拒绝回调的责任 - 并且让你自己回调地狱。正是Promise应该解决的问题。
在这两个片段中,只要您看到count > 0
并调用doEdits
,就会放弃之前的Promise,实例化一个新的Promise,最后得到一条un resolve
的踪迹你承诺在你身后。您需要将解决方案和拒绝功能传递到新承诺中,并确保在新承诺解决或拒绝时适当地解决或拒绝这些功能。
不要这样做
function doEdits(previousPromise) {
someDB.performEdits()
.then((count) => {
if(count > 0) {
doEdits(this);
} else {
resolve();
}
})
};
return new Promise((resolve, reject) => {
someDB.init()
.then(() => {
someDB.performEdits()
.then((count) => {
if(count > 0) {
doEdits(this);
} else {
resolve();
}
})
})
});
因为它是浪费的,并且如果performEdits迭代33拒绝,也不处理这种情况。从理论上讲,这可能会奏效,但要推理起来要困难得多。