简体   繁体   English

如何打破承诺链?

[英]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. 我知道也有类似的问题,但是我还没有看到任何解决此链接模式的问题。

I have the following: 我有以下几点:

    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 

The problem that I'm encountering is that I'm calling tryOpenStream many times even after I've captured a result . 我遇到的问题是即使我捕获了result后,我也多次调用tryOpenStream

Options I'm considering: 我正在考虑的选项:

  • Raise some global flag that just prevents further execution from within the chain. 提出一些全局标志,仅阻止其在链中进一步执行。 Yuck, because the chain still proceeds, it's just emptied. uck,因为链条仍然在前进,所以它被清空了。
  • throw new Error(result) instead of return result . throw new Error(result)而不是return result This would break the chain (I think...) but it's misusing Error and would be easily misunderstood by another developer. 这将打破链条(我认为...),但是它滥用了Error ,并且很容易被其他开发人员误解。

How can I break this chain at return result; 如何在return result;打破此链return result; ?

UPDATE 1 更新1

I'm trying the following: 我正在尝试以下方法:

   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.") })();
    });

However no calls to runTest are invoked. 但是,不会调用runTest的任何调用。 This is a bit of new syntax for me so I'll research some and update with any findings. 这对我来说是个新语法,因此我将进行一些研究并根据发现进行更新。

UPDATE 2 更新2

I was missing the () to invoke the reduceRight . 我缺少()来调用reduceRight Though now I'm seeing that reject called even with success... though when I step through, that rejection isn't invoked. 尽管现在我看到即使成功也reject调用...尽管当我逐步执行时,不会调用该拒绝。 It's as if by the time I get a result back, all links in the chain have been invoked. 好像到我返回结果时一样,链中的所有链接都已被调用。

Try using this: 尝试使用此:

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)

Although I do wonder why you can't use an exception to denote your tryOpenStream failed. 尽管我确实想知道为什么您不能使用异常来表示tryOpenStream失败。 That would actually simplify your code some. 这实际上可以简化您的代码。

Both flags and exceptions can be used, but as you noticed they're not the proper tool. 标志和异常都可以使用,但是正如您注意到的那样,它们不是正确的工具。

Instead, use recursion, like in @IsiahMeadows' answer, or a right fold: 相反,请使用递归(例如@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));

or better written as 或更好地写为

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"))();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM