如何顺序调用延迟函数? [英] How to call deferred functions sequentially?

查看:84
本文介绍了如何顺序调用延迟函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码:

<?php
if(isset($_GET['m'])) {
    $m = $_GET['m'];
    sleep($m);
    print "done, m=$m";
    die;
}
?>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>
<script>

    function w(s) {
        document.body.innerHTML = document.body.innerHTML+ "<br>" + s
    }

    function aaa(def) {
        w("begin aaa");
        $.ajax({
            type: "GET",
            data: {
                m: 5
            }
        }).done(function(html) {
            w(html);
            def.resolve();
        });
    }


    function bbb(def) {
        w("begin bbb");
        $.ajax({
            type: "GET",
            data: {
                m: 1
            }
        }).done(function(html) {
            w(html);
            def.resolve();
        });
    }

    $(function() {

        $.when(
            $.Deferred(function(d) { aaa(d) }).promise(),
            $.Deferred(function(d) { bbb(d) }).promise()
        ).done(function() {
            w("OK")
        });
    })
</script>

我希望第二个函数等待第一个函数完成,也就是说,我的输出应该是

begin aaa
   <--pause
done, m=1
begin bbb
   <--pause
done, m=5
OK

相反,我得到了

begin aaa
begin bbb
   <--pause
done, m=1
   <--pause
done, m=5
OK

我想我误解了延期工作的基本原理-任何人都可以找到答案吗?

解决方案

如果它们之间没有依赖性,您如何期望它们按顺序执行? $.when对承诺的评估没有影响,也没有影响,它只是等待每个承诺都得到解决.

您的代码要复杂得多. $.ajax已经返回了一个Promise,当收到Ajax响应时,它会被解决,因此您只需从函数中将其返回即可.如果要按顺序执行它们,可以通过 .then :

这些过滤器函数可以返回要传递给Promise的.done().fail()回调的新值,或者可以返回另一个可观察对象(Deferred,Promise等),该对象将传递其已解决/已拒绝状态,承诺的回调的值.

因此您的代码简化为:

function aaa() {
    w("begin aaa");
    return $.ajax({
        type: "GET",
        data: {
            m: 5
        }
    }).done(w);
}


function bbb() {
    w("begin bbb");
    return $.ajax({
        type: "GET",
        data: {
            m: 1
        }
    }).done(w);
}

aaa().then(bbb).done(function() { w('ok'); });

在这里,aaa().then(bbb)创建您需要的依赖项.这基本上意味着一旦aaa的承诺得到解决,就执行bbb".另外,.then返回一个新的promise,当bbb返回的promise被解析时,该新promise将被解析,这使您可以在aaabbb的promise都被解析时执行一个函数. >

也许这些可以帮助您更好地理解承诺(和延期):


不带$.ajax的示例:

function aaa() {
    var def = new $.Deferred();
    setTimeout(function() {
        def.resolve(21);
    }, 3000);
    return def.promise();
}

function bbb(v) {
    var def = new $.Deferred();
    setTimeout(function() {
        def.resolve(v * 2);
    }, 1000);
    return def.promise();
}

// aaa -> bbb -> console.log
// The value is logged after 3 + 1 seconds
aaa().then(bbb).done(function(v) { console.log(v); }); // 42

// (aaa | bbb) -> console.log
// The value is logged after max(3, 1) seconds and both resolved values are
// passed to the final promise
$.when(aaa(), bbb(5)).done(function(v) { console.log(v); }); // [21, 10]

My code:

<?php
if(isset($_GET['m'])) {
    $m = $_GET['m'];
    sleep($m);
    print "done, m=$m";
    die;
}
?>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>
<script>

    function w(s) {
        document.body.innerHTML = document.body.innerHTML+ "<br>" + s
    }

    function aaa(def) {
        w("begin aaa");
        $.ajax({
            type: "GET",
            data: {
                m: 5
            }
        }).done(function(html) {
            w(html);
            def.resolve();
        });
    }


    function bbb(def) {
        w("begin bbb");
        $.ajax({
            type: "GET",
            data: {
                m: 1
            }
        }).done(function(html) {
            w(html);
            def.resolve();
        });
    }

    $(function() {

        $.when(
            $.Deferred(function(d) { aaa(d) }).promise(),
            $.Deferred(function(d) { bbb(d) }).promise()
        ).done(function() {
            w("OK")
        });
    })
</script>

I'm expecting the second function to wait for the first one to complete, that is, my output should be

begin aaa
   <--pause
done, m=1
begin bbb
   <--pause
done, m=5
OK

Instead I'm getting

begin aaa
begin bbb
   <--pause
done, m=1
   <--pause
done, m=5
OK

I guess I'm misunderstanding something fundamental about how deferreds work - can anyone shed a light?

解决方案

How do you expect them to be executed in order if there is no dependency between them? $.when doesn't have and cannot have an influence on the evaluation of the promise, it just waits until each of the promises is resolved.

Your code is way more complicated then it needs to be. $.ajax already returns a promise which gets resolved when the Ajax response was received, so you can just return it from the functions. If you want to execute them in sequence, you can chain them via .then:

These filter functions can return a new value to be passed along to the promise's .done() or .fail() callbacks, or they can return another observable object (Deferred, Promise, etc) which will pass its resolved / rejected status and values to the promise's callbacks.

So your code simplifies to:

function aaa() {
    w("begin aaa");
    return $.ajax({
        type: "GET",
        data: {
            m: 5
        }
    }).done(w);
}


function bbb() {
    w("begin bbb");
    return $.ajax({
        type: "GET",
        data: {
            m: 1
        }
    }).done(w);
}

aaa().then(bbb).done(function() { w('ok'); });

Here, aaa().then(bbb) creates the dependency you need. It basically means "once aaa's promise is resolved, execute bbb". In addition, .then returns a new promise, which gets resolved when the promise returned by bbb gets resolved, which allows you to execute a function when the promises of both, aaa and bbb are resolved.

Maybe these help you to understand promises (and deferreds) better:


Example without $.ajax:

function aaa() {
    var def = new $.Deferred();
    setTimeout(function() {
        def.resolve(21);
    }, 3000);
    return def.promise();
}

function bbb(v) {
    var def = new $.Deferred();
    setTimeout(function() {
        def.resolve(v * 2);
    }, 1000);
    return def.promise();
}

// aaa -> bbb -> console.log
// The value is logged after 3 + 1 seconds
aaa().then(bbb).done(function(v) { console.log(v); }); // 42

// (aaa | bbb) -> console.log
// The value is logged after max(3, 1) seconds and both resolved values are
// passed to the final promise
$.when(aaa(), bbb(5)).done(function(v) { console.log(v); }); // [21, 10]

这篇关于如何顺序调用延迟函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆