如何使用jQuery';是否使用自定义javascript对象创建延迟对象?

如何使用jQuery';是否使用自定义javascript对象创建延迟对象?,javascript,jquery,jquery-deferred,Javascript,Jquery,Jquery Deferred,我有一个标准的javascript对象,它的原型使用一个.start()方法进行扩展,该方法使用两个回调作为参数:success和failure。此方法执行一些异步处理(它是而不是AJAX),并根据此处理的结果调用成功或失败回调 以下是如何将其计划化: function MyObject() { } MyObject.prototype.start = function(successCallback, errorCallback) { (function(s, e) {

我有一个标准的javascript对象,它的原型使用一个
.start()
方法进行扩展,该方法使用两个回调作为参数:
success
failure
。此方法执行一些异步处理(它是而不是AJAX),并根据此处理的结果调用成功或失败回调

以下是如何将其计划化:

function MyObject() {
}

MyObject.prototype.start = function(successCallback, errorCallback) {
    (function(s, e) {
        window.setTimeout(function() {
            if (Math.random() < 0.8) {
                s();    
            } else {
                e();    
            }
        }, 2000);    
    })(successCallback, errorCallback);
}
此数组中元素的顺序很重要。我需要在数组的每个元素上连续触发
.start()
方法,但仅在前一个元素完成后触发(即调用成功回调)。如果发生错误(调用失败回调),我希望停止执行,不再对数组的其余元素调用.start方法

我可以通过使用递归函数天真地实现这一点:

function doProcessing(array, index) {
    array[index++].start(function() {
        console.log('finished processing the ' + index + ' element');
        if (index < array.length) {
            doProcessing(array, index);
        }
    }, function() {
        console.log('some error ocurred');
    });
}

doProcessing(arr, 0);
函数数据处理(数组、索引){
数组[index++].start(函数(){
log('处理完'+index+'元素');
if(索引<数组长度){
数据处理(数组、索引);
}
},函数(){
log(“发生了一些错误”);
});
}
数据处理(arr,0);
这很好,但是看看jQuery1.5中引入的代码,我认为这段代码还有改进的余地。不幸的是,我还不觉得很舒服,我正在努力学习

所以我的问题是,是否有可能修改我的原始代码并利用这个新的API?如果有,您能给我提供一些指导吗


下面是我的实现的一个例子。

您可以这样做:()

函数MyObject(){
}
MyObject.prototype.start=函数(队列){
var deferred=$.deferred();
//仅当队列中的所有其他内容都已完成并成功时才执行此操作
$.when.apply(jQuery,queue).done(function(){
setTimeout(函数(){
if(Math.random()<0.8){
延迟。解决();
}否则{
拒绝();
}
}, 2000); 
});
延期归还;
}
var arr=[new MyObject(),new MyObject(),new MyObject()];
var queue=新数组();
$。每个(arr,函数(索引,值){
queue.push(value.start)(队列)
.done(函数(){
console.log('successed'+索引);
})
.fail(函数(){
console.log('failed'+索引);
}));
});

<>虽然不太确定你会认为这是一个进步。

你的实现没有错。众所周知,使用jQuery并不总是最好的方法

我会这样做:(无需修改MyObject类..)

函数数据处理(数组、索引){
var defer=new$.Deferred();
$.when(延迟)。然后(数据处理);
数组[index++].start(函数(){
日志('已完成处理'+index+'元素');
if(索引<数组长度){
解析(数组、索引);
}
},函数(){
日志('出现一些错误=>中断进程');
});
};
正如您所看到的,与普通JavaScript方法相比,没有什么真正的优势


以下是我的建议:

当我们编程时,记住掌握原则或指导方针是非常重要的

获得高内聚和低耦合意味着我们的代码将更好,更可重用,更易于维护

因此,类MyObject不能知道队列存在。MyObject将了解自己的特性和方法以及其他任何东西

// Class MyObject

function MyObject(name) {
    this.name = name;
}

MyObject.prototype.start = function() {

    var deferred = $.Deferred();
    var self = this;
    setTimeout(function() {
        if (Math.random() <= 0.8) {
            console.log(self.name + "... ok");
            deferred.resolve();
        } else {
            console.log(self.name + "... fail");
            deferred.reject();
        }
    }, 1000);

    return deferred.promise();
} 
我已经为jQuery构建了一个插件:iterativeWhen。它适用于jQuery1.8及更高版本

$.iterativeWhen = function () {

    var deferred = $.Deferred();
    var promise = deferred.promise();

    $.each(arguments, function(i, obj) {

        promise = promise.then(function() {
            return obj();
        });
    });

    deferred.resolve();

    return promise;
}; 

jshiddle here:

+1看到顶级回答者提出一个好问题总是很好的。自我回答这个问题?看起来很有趣,唯一的问题是我不能修改
MyObject
。顺便问一下,你的最终目标是什么?延迟的真正作用在于您可以将多个回调注册到回调队列中。因此,不管(a)同步函数已经完成,您仍然可以注册其他回调。此外,注册多个回调非常容易。这听起来像你需要的东西吗?我真正的目标是通过尝试看看它是否可以应用于某些场景来了解Deffered是如何工作的。你的回答在这方面很有帮助。非常感谢。
function doProcessing(array, index) {
    var defer = new $.Deferred();

    $.when(defer).then(doProcessing);

    array[index++].start(function() {
        log('finished processing the ' + index + ' element');
        if (index < array.length) {
            defer.resolve(array, index);
        }
    }, function() {
        log('some error ocurred => interrupting the process');
    });
};
// Class MyObject

function MyObject(name) {
    this.name = name;
}

MyObject.prototype.start = function() {

    var deferred = $.Deferred();
    var self = this;
    setTimeout(function() {
        if (Math.random() <= 0.8) {
            console.log(self.name + "... ok");
            deferred.resolve();
        } else {
            console.log(self.name + "... fail");
            deferred.reject();
        }
    }, 1000);

    return deferred.promise();
} 
// Create array of instances
var objectArray = [ new MyObject("A"), new MyObject("B"), new MyObject("C") ];

// Create array of functions to call start function
var functionArray = [];
$.each(objectArray, function(i, obj) {
    functionArray.push(
        function() {
           return obj.start();
        }
    );
});

// Chain three start calls 
$.iterativeWhen(functionArray[0], functionArray[1], functionArray[2])
.done(function() {

    console.log("First: Global success");

    // Chain three start calls using array
    $.iterativeWhen.apply($, functionArray)
    .done(function() {
        console.log("Second: Global success");
    })
    .fail(function() {
        console.log("Second: Global fail");
    });

})
.fail(function() {
    console.log("First: Global fail");
});
$.iterativeWhen = function () {

    var deferred = $.Deferred();
    var promise = deferred.promise();

    $.each(arguments, function(i, obj) {

        promise = promise.then(function() {
            return obj();
        });
    });

    deferred.resolve();

    return promise;
};