【问题标题】:Chaining functions that return deferred objects返回延迟对象的链接函数
【发布时间】:2017-06-15 21:13:12
【问题描述】:

我有一些函数会返回 jQuery Deferred 对象,但我无法将它们链接起来并处理结果。

考虑以下示例:

const start = Date.now();

// Print a message with a timestamp.
function log (v) {
    console.log(`${Date.now() - start} ${v}`);
}

// Return a deferred function that resolves 1 second later with 'value'.
function test (value) {
    log(`test(${value})`);
    return $.Deferred(function (def) {
        window.setTimeout(function () {
            log(`resolve(${value})`);
            def.resolve(value);
        }, 1000);
    });
}

// Example:
test(42)
    .then(function (v) { log(v); })
    .then(test(99))
    .then(function (v) { log(v); })
    .then(function () { log('done'); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

这是应该运行test(42),然后对其结果做一些事情,然后运行test(99),然后对这些结果做一些事情,一切都按顺序进行。但是,它实际上输出(第一个数字是自程序启动以来的 ms):

0 test(42)
0 test(99)
1003 resolve(42)
1003 42
1003 undefined    <-- supposed to be 99
1005 done
1005 resolve(99)

因此,两个tests 在开始时同时被调用,而其他一切都关闭了。我想要它输出的是这样的:

0 test(42)
1000 resolve(42)
1000 42
1000 test(99)
2000 resolve(99)
2000 99
2000 done

我怎样才能做到这一点?我尝试返回$.Deferred(...).promise(),但行为没有改变,我也尝试使用done而不是then,但唯一的变化是它第二次打印42而不是undefined

【问题讨论】:

    标签: javascript jquery jquery-deferred


    【解决方案1】:

    每个延迟只解决一次。对于每个延迟链,您必须正确附加它们。此外,第二次调用 test 需要在一个函数中,这样它就不会立即执行。

    const start = Date.now();
    
    // Print a message with a timestamp.
    function log (v) {
        console.log(`${Date.now() - start} ${v}`);
    }
    
    // Return a deferred function that resolves 1 second later with 'value'.
    function test (value) {
        log(`test(${value})`);
        return $.Deferred(function (def) {
            window.setTimeout(function () {
                log(`resolve(${value})`);
                def.resolve(value);
            }, 1000);
        });
    }
    
    // Example:
    test(42)
        .then(function (v) { log(v); })
        .then(function () {
            test(99)
               .then(function (v) { log(v); })
               .then(function () { log('done'); });
        });
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 啊,我明白了,谢谢。像这样嵌套它们是唯一的方法吗?因此,如果我要构建一个带有 for 循环或其他东西的长链,我必须编写一些辅助函数来按顺序执行它们,或者将所有内容巧妙地嵌入到这种嵌套形式中?
    • 一旦一个 deferred 解析,它会执行所有的 then() 附加到它,不管一个是否包含另一个 deferred。所以你必须牢记这一点。
    • 顺便说一句,我根据你的建议做了一个小实验,如果我只是第二次调用 test ,它实际上 似乎可以正常工作一个函数(返回该延迟对象),即使没有嵌套 like this。也许如果then 处理程序返回了一些 thenable,它会改变链的其余部分正在运行的内容?
    • 你能分享一个你的实验链接吗?
    • 呵呵,有意思。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 2018-04-12
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-08
    相关资源
    最近更新 更多