如何使用确认警报并返回AJAX承诺?

时间:2015-12-24 13:39:09

标签: javascript jquery ajax promise

我有一个返回AJAX承诺的现有函数。我想更新此函数以在运行AJAX调用之前显示确认警报,但代码的其他部分使用此函数并且已经期待一个承诺。

这是我原来的功能:

function doTheDeed() {
  return $.ajax({
    url: '/api/delete/123',
    method: 'POST'
  }).done(function () {
    alert('The deed is done.');
  });
}

doTheDeed().done(function {} { /*Do something else*/ });

现在我想在运行AJAX调用之前与用户确认。如何维护返回承诺的API协议,同时等待用户确认或取消?

function doTheDeed() {
  bootbox.confirm('Are you sure?', function (result) {
    if (result) {
      // Too late to return a promise, promise should've been returned a long time ago
      return $.ajax({
        url: '/api/delete/123',
        method: 'POST'
      }).done(function () {
        alert('The deed is done.');
      });
    } else {
      //return what??
    }
  });
}

doTheDeed().done(function {} { /*Do something else*/ });

我是否需要根据用户的回复有条件地返回不同的承诺?

2 个答案:

答案 0 :(得分:3)

您可以使用jQuery的Deferreds吗?

function doTheDeed() {
    var def = $.Deferred();

    bootbox.confirm('Are you sure?', def.resolve);

    return def.promise().then(function(result) {
        return result ? $.post('/api/delete/123') : "no go";
    });
}

doTheDeed().done(function (data) { 
    if (data == 'no go') {
        // user declined
    } else {
        // item deleted
    }
}).fail(function(err) {
    // something failed
});

答案 1 :(得分:2)

基于Adeneo的回答,并坚持最低级别的promisifying原则,bootbox可以通过bootbox.confirm()的可重用承诺进行monkeypatched,而不必侵入bootbox本身。

如果你这样做,那就合适了:

  • 允许调用者指定质询文本和noGo消息。
  • 向错误路径发送noGo条件。
if(!bootbox.confirmAsync) {
    bootbox.confirmAsync = function (challenge, noGoMessage) {
        challenge = challenge || 'Are you sure?';
        noGoMessage = noGoMessage || 'User declined';
        return jQuery.Deferred(function (def) {
            bootbox.confirm(challenge, function (confirmed) {
                confirmed ? def.resolve() : def.reject(new Error(noGoMessage));
            });
        }).promise();
    }
}

doTheDeed()将包含一个以bootbox.confirmAsync(...)开头的完全传统的链,例如:

function doTheDeed () {
    return bootbox.confirmAsync('Are you sure you want to delete?', 'User declined to delete')
    .then(function (data) {
        return $.post('/api/delete/123');
    })
    .then(null, function (err) {
        // if user declined, then 'User declined to delete' will come back as err.message
        console.log(err.message);
        return err; // jQuery v<3.0
        // throw err; // jQuery v>=3.0
    });
}