如何打破承诺链?
How to break a promise chain?
I'm aware that there are similar questions, but I haven't seen any that address this chaining pattern.
我有以下内容:
var runTests = function (chain, resolutionTest) {
return chain.then(function (result) {
if (result)
return result; // Early return if the previous tests were successful. This is where I want to prevent other attempts.
const attempt = tryOpenStream(resolutionTest).then(streamToDom);
return attempt;
});
}
// from someplace else
numTests = resolutionTests.length;
return resolutionTests.reduce(runTests, Promise.resolve()); // start reduce with an empty promise
我遇到的问题是我多次调用 tryOpenStream
,甚至在我捕获 result
之后也是如此。
我正在考虑的选项:
- 提出一些全局标志,只是阻止从链内进一步执行。糟糕,因为链条仍在继续,它只是被清空了。
throw new Error(result)
而不是 return result
。这会破坏链条(我认为......)但它滥用 Error
并且很容易被其他开发人员误解。
如何在 return result;
打破这条链?
更新 1
我正在尝试以下操作:
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest() {
return tryOpenStream(resolutionTest).then(streamToDom).then(function (result) {
if (result)
return result;
else
return runMoreTests();
});
};
}
return resolutionTestBuilder.buildTests().then(function (resolutionTests) {
numTests = resolutionTests.length;
return resolutionTests.reduceRight(makeTest, function () { Promise.reject("No resolutions succeeded.") })();
});
但是没有调用 runTest
。这对我来说有点新语法,所以我会研究一些并更新任何发现。
更新 2
我缺少 ()
来调用 reduceRight
。虽然现在我看到 reject
即使成功也被调用了……但是当我逐步执行时,不会调用拒绝。好像当我得到返回结果时,链中的所有链接都已被调用。
试试这个:
function runTests(resolutionTest) {
return tryOpenStream(resolutionTest).then(streamToDom)
}
// from someplace else
function loop(tests, i) {
if (i === tests.length) return undefined
return runTests(tests[i]).then(function (result) {
if (result) return result
return loop(tests, i + 1)
})
}
return loop(resolutionTests, 0)
尽管我确实想知道为什么您不能使用异常来表示您的 tryOpenStream
失败。这实际上会简化您的代码。
标志和异常都可以使用,但正如您所注意到的,它们不是合适的工具。
相反,使用递归,如@IsiahMeadows 的回答,或正确的折叠:
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest(result) {
if (result)
return result;
return tryOpenStream(resolutionTest).then(streamToDom).then(runMoreTests);
};
}
return Promise.resolve(resolutionTests.reduceRight(makeTest, x => x)(undefined));
或更好地写成
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest() {
return tryOpenStream(resolutionTest).then(streamToDom).then(result => {
if (result)
return result;
else
return runMoreTests();
});
};
}
return resolutionTests.reduceRight(makeTest, () => Promise.reject("nothing succeeded"))();
I'm aware that there are similar questions, but I haven't seen any that address this chaining pattern.
我有以下内容:
var runTests = function (chain, resolutionTest) {
return chain.then(function (result) {
if (result)
return result; // Early return if the previous tests were successful. This is where I want to prevent other attempts.
const attempt = tryOpenStream(resolutionTest).then(streamToDom);
return attempt;
});
}
// from someplace else
numTests = resolutionTests.length;
return resolutionTests.reduce(runTests, Promise.resolve()); // start reduce with an empty promise
我遇到的问题是我多次调用 tryOpenStream
,甚至在我捕获 result
之后也是如此。
我正在考虑的选项:
- 提出一些全局标志,只是阻止从链内进一步执行。糟糕,因为链条仍在继续,它只是被清空了。
throw new Error(result)
而不是return result
。这会破坏链条(我认为......)但它滥用Error
并且很容易被其他开发人员误解。
如何在 return result;
打破这条链?
更新 1
我正在尝试以下操作:
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest() {
return tryOpenStream(resolutionTest).then(streamToDom).then(function (result) {
if (result)
return result;
else
return runMoreTests();
});
};
}
return resolutionTestBuilder.buildTests().then(function (resolutionTests) {
numTests = resolutionTests.length;
return resolutionTests.reduceRight(makeTest, function () { Promise.reject("No resolutions succeeded.") })();
});
但是没有调用 runTest
。这对我来说有点新语法,所以我会研究一些并更新任何发现。
更新 2
我缺少 ()
来调用 reduceRight
。虽然现在我看到 reject
即使成功也被调用了……但是当我逐步执行时,不会调用拒绝。好像当我得到返回结果时,链中的所有链接都已被调用。
试试这个:
function runTests(resolutionTest) {
return tryOpenStream(resolutionTest).then(streamToDom)
}
// from someplace else
function loop(tests, i) {
if (i === tests.length) return undefined
return runTests(tests[i]).then(function (result) {
if (result) return result
return loop(tests, i + 1)
})
}
return loop(resolutionTests, 0)
尽管我确实想知道为什么您不能使用异常来表示您的 tryOpenStream
失败。这实际上会简化您的代码。
标志和异常都可以使用,但正如您所注意到的,它们不是合适的工具。
相反,使用递归,如@IsiahMeadows 的回答,或正确的折叠:
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest(result) {
if (result)
return result;
return tryOpenStream(resolutionTest).then(streamToDom).then(runMoreTests);
};
}
return Promise.resolve(resolutionTests.reduceRight(makeTest, x => x)(undefined));
或更好地写成
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest() {
return tryOpenStream(resolutionTest).then(streamToDom).then(result => {
if (result)
return result;
else
return runMoreTests();
});
};
}
return resolutionTests.reduceRight(makeTest, () => Promise.reject("nothing succeeded"))();