jQuery包装延迟和承诺

时间:2014-02-12 09:36:00

标签: jquery promise deferred

我有一个jq替换标准确认对话框。

我允许用户传入一个函数,如果用户点击ok,将会调用该函数。

传入的函数可能会像ajax调用那样调用长时间运行的异步任务,有时候不会,我想满足这两者的需要。

我使用此解决方案作为基础(https://stackoverflow.com/a/19374933

我想要实现的是这样的:

MyConfirmation('A Title', 'A message to the user', function() {
    $.get('/some/bigdata/longrunning');
}
).then(function() {
    // add to dom here
});

这是MyConfirmation:

MyConfirmation = function (title, message, ok) {
    var d = $.Deferred();
    $('<div/>')
        .text(message)
        .dialog({
                    buttons: {
                "Ok": function () {
                    if($.isFunction(ok)) {
                        ok.apply();
                    }
                    $(this).dialog("close");
                    d.resolve(true);
                    return true;
                },
                "Cancel": function () {
                    $(this).dialog("close");
                    d.resolve(false);
                    return false;
                }
            },
            close: function(event, ui) {
                $(this).remove();
            },
            resizable: false,
            draggable: false,
            width: 'auto',
            title: title,
            modal: true
        });

    return d.promise();
};

我想理想地与我的deferred结合使用,返回true或false以指示用户是单击确定还是取消。

我知道我可以在$ .get返回的承诺上使用.done方法但是如何使我的解决方案工作

3 个答案:

答案 0 :(得分:1)

  

我允许用户传入一个函数,如果用户点击ok,将会调用该函数。

别。只需从ok函数中删除MyConfirmation参数,然后只返回按钮点击的承诺。然后,用户可以根据需要将其功能链接起来 - 或者做更多。

你的电话应该是这样的:

MyConfirmation('A Title', 'A message to the user').then(function(okPressed) {
    if (okPressed)
        return $.get('/some/bigdata/longrunning');
}).then(function(longruningResult) {
    // add to dom here
});

当按下 Cancel 按钮时,您也可能reject()承诺,那么您不需要进行布尔okPressed检查,而是可以使用单独的错误处理程序。

答案 1 :(得分:0)

我认为你应该使用ajax调用作为返回的承诺:

MyConfirmation('A Title', 'A message to the user', function() {
    return $.get('/some/bigdata/longrunning');
}
).then(function() {
    // add to dom here
});

MyConfirmation功能:

MyConfirmation = function (title, message, ok) {
    var d = $.Deferred();
    $('<div/>')
        .text(message)
        .dialog({
                    buttons: {
                "Ok": function () {
                    if($.isFunction(ok)) {
                        ok().then(function() {
                            d.resolve(true);
                        });
                    }
                    $(this).dialog("close");
                    return true;
                },
                "Cancel": function () {
                    $(this).dialog("close");
                    d.resolve(false);
                    return false;
                }
            },
            close: function(event, ui) {
                $(this).remove();
            },
            resizable: false,
            draggable: false,
            width: 'auto',
            title: title,
            modal: true
        });

    return d.promise();
};

这为ajax promise本身

添加了一个解决对话框的条件

免责声明:未经测试:)

答案 2 :(得分:0)

继Pandaiolo的回复之后,我意识到我应该在我的调用函数中返回ajax调用。当传入的函数完成时,那个和我自己的链接延迟了。

当传入的函数没有返回延迟(通过使用$.when)并且它有效时(参见How can I determine if a jQuery object is deferred?

来捕获这些实例的小调整

MyConfirmation成为:

MyConfirmation = function (title, message, ok) {
    var d = $.Deferred();
    $('<div/>')
        .text(message)
        .dialog({
                    buttons: {
                "Ok": function () {
                    if($.isFunction(ok)) {
                        $.when(ok.apply()).then(function() {
                            d.resolve(true);
                        });
                    } else {
                        d.resolve(true);
                    }
                    $(this).dialog("close");
                    return true;
                },
                "Cancel": function () {
                    $(this).dialog("close");
                    d.resolve(false);
                    return false;
                }
            },
            close: function(event, ui) {
                $(this).remove();
            },
            resizable: false,
            draggable: false,
            width: 'auto',
            title: title,
            modal: true
        });

    return d.promise();
};