返回延迟对象的链接函数

时间:2017-06-15 21:13:12

标签: javascript jquery jquery-deferred

我有一些函数可以返回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>
&#13;
&#13;
&#13;

这是假设运行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)

因此,test的所有内容都会在开始时同时被调用,而其他所有内容都会关闭。我想要输出的内容类似于:

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

我该如何使这项工作?我尝试返回$.Deferred(...).promise(),但行为没有变化,我也尝试使用done代替then,但唯一的变化是第二次打印42而不是undefined {1}}。

1 个答案:

答案 0 :(得分:1)

每个延期只解决一次。对于每个延迟链,您必须正确附加它们。第二次测试调用需要在函数中,以便它不会立即执行。

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'); });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>