【问题标题】:jquery convert promise cascadejQuery转换承诺级联
【发布时间】:2016-12-16 22:24:10
【问题描述】:

我有一个关于 jquery 承诺级联的问题,我想简化它。我有一个正在工作的级联函数(func1)。我在执行下一个功能之前设置了 2 秒超时。我想复制并将其转换为数组缩减形式(func2),但它不像 func1 那样工作(超时不一样)。代码如下:

var Makes=[1,2,3,5,8];
$(document).ready(function(){
    //func1(); //WORKS
    func2();   //NOT WORKS LIKE func1

});

function func1(){
    timeout().then(function(){
       console.log("1");
       return timeout();
    }).then(function(){
       console.log("2");
       return timeout();
    }).then(function(){
       console.log("3");
       return timeout();
    }).then(function(){
       console.log("4");
       return timeout();
    }).then(function(){
       console.log("5");
       return timeout();
    });
}

function func2(){
    /*Makes.reduce(function(Models,Idx){
        return timeout().then(function(){
            console.log(Idx);
            return timeout();
            //return $.when(timeout());
        });
    },0);*/
    Makes.reduce(function(Models,Idx){
        return Models.then(function(){
            return timeout().then(function(){
                console.log(Idx);
                return timeout();
                //return $.when(timeout());
            });
        });
    },0);
}

function timeout(){
    var d = $.Deferred();
    setTimeout(function(){ 
        console.log("wait for 2 sec!");
        d.resolve(); 
    },2000);
    return d.promise();
}

【问题讨论】:

  • 因为reduce函数不处理promise并等待它被解决
  • 你想在这里实现什么
  • 我想让 func2 的行为与 func1 相同,但使用数组 reduce 代替
  • 我编辑了 func2 来处理 Models.then 中的 timeout() 但也没有工作。现在我收到一个错误“Models.then 不是函数”

标签: jquery promise deferred


【解决方案1】:

您不应该在reduce 回调中返回timeout().then,而是建立在您从上一次迭代中获得的承诺:Models.then。你应该给出一个初始的承诺,一个立即解决的承诺($.when()):

function func2(){
    Makes.reduce(function(Models, Idx) {
        return Models.then(function () {
            return timeout().then(function () {
                console.log(Idx);
            });
        });
    }, $.when()); // resolved starter promise
}

var Makes=[1,2,3,5,8];
$(document).ready(function(){
    func2(); 
});

function func2(){
    Makes.reduce(function(Models, Idx) {
        return Models.then(function () {
            return timeout().then(function () {
                console.log(Idx);
            });
        });
    }, $.when());
}

function timeout(){
    var d = $.Deferred();
    setTimeout(function(){ 
        console.log("wait for 2 sec!");
        d.resolve(); 
    },2000);
    return d.promise();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

或者,您可以使用“递归”类型的函数来实现异步循环:

function func2(){
    (function repeat(Idx) {
        if (Idx >= Makes.length) return;
        timeout().then(function () {
            console.log(Makes[Idx]);
            repeat(Idx+1);
        });
    }(0));
}

var Makes=[1,2,3,5,8];
$(document).ready(function(){
    func2(); 
});

function func2(){
    (function repeat(Idx) {
        if (Idx >= Makes.length) return;
        timeout().then(function () {
            console.log(Makes[Idx]);
            repeat(Idx+1);
        });
    }(0));
}

function timeout(){
    var d = $.Deferred();
    setTimeout(function(){ 
        console.log("wait for 2 sec!");
        d.resolve(); 
    },2000);
    return d.promise();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【讨论】:

  • 感谢 trincot。它像我想要的那样工作。没想到$.Deferred().resolve()可以用在reduce数组的初值中。
  • 更简洁地说,对于一个已解决的承诺,我们通常会写成$.when()
  • 感谢@Roamer-1888,我用更短的语法更新了我的答案。
  • 由于$.when() 的含义并不完全清楚,所以我通常会包含一个注释,即使是对我自己也是如此。
  • @Roamer-1888,感谢您添加评论,但您犯了拼写错误 ;-) 现已更正。
猜你喜欢
  • 2015-02-18
  • 1970-01-01
  • 1970-01-01
  • 2015-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-24
  • 2021-01-27
相关资源
最近更新 更多