【问题标题】:Returning Promises for use in click handlers返回 Promise 以在点击处理程序中使用
【发布时间】:2014-02-01 19:31:13
【问题描述】:

我正在尝试从 AJAX 方法返回承诺,并了解如何使用它们使我的代码更易于阅读/功能化。我目前的情况是有一个函数getBookIds 向数据库发出AJAX 调用,以根据其ID 返回一本书的标题。表中有五本书和一个锚标记,其文本属性对应于每本书。单击所有锚标记后,我希望触发其他一些花哨的 AJAX 方法。这是我到目前为止所得到的:

HTML
<a href="#">1</a> 
<a href="#">3</a> 
<a href="#">4</a> 
<a href="#">5</a> 
<a href="#">7</a>

JS

 //hacky globals
 var bookArray = [];
 bookArray.length = $('a').length;

 //ajax function
 function getBookIds(data) {
     return $.ajax({
         type: "POST",
         url: "Service.asmx/GetBookById",
         data: JSON.stringify({
             'titleId': data
         }),
         dataType: "json",
         contentType: "application/json"
     });
 }
 //click handler
 $('a').on('click', function () {
     var index = $('a').index($(this));
     var titleId = $(this).text();
     getBookIds(titleId).done(function (results) {
         bookArray[index] = results.d;
         var isEmpty = arrayChecker(bookArray);
         fancyAjax(isEmpty);
     });
 });
 //checks for undefined values in the array
 function arrayChecker(array) {
     var isEmpty = 0;
     $.each(array, function (key, val) {
         if (val === undefined) {
             isEmpty++;
         }
     });
     return (isEmpty > 0);
 }
 //bool comes from arrayChecker if no undefined then go AJAX
 function fancyAjax(bool) {
     if (!bool) {
         alert('alert message for fancy stuff');
     }
 }

这是一个人为的例子,但我正在努力寻找如何将这些承诺融入我的日常工作中。这只是首先利用承诺/延迟的力量的一个坏例子吗?似乎不是我在 AJAX 上的 success 回调,而是在 done 中汇总了我的所有逻辑。有什么更好地解决这个问题的建议吗?

【问题讨论】:

  • 好问题,但它属于:codereview.stackexchange.com
  • @JohnStricler 并非每个带有代码的问题都属于 codereview。他在问一个概念,代码是一个例子而不是生产代码。这个问题是这里的主题,甚至还不错:)
  • @JohnStrickler 我也在那里发帖,我很高兴将它迁移到最合适的地方。

标签: javascript jquery ajax promise


【解决方案1】:

我希望在点击所有锚标记后触发其他一些花哨的 AJAX 方法。

听起来您希望为每次点击获得一个承诺,然后您可以将其组合成一个针对所有点击的承诺。重点不是使用全局booksArray,而是使用一组promise。

function getBookIds(data) { … } //ajax function as before

var promises = $('a').map(function() {
    var $this = $(this),
        click = $.Deferred();
    $this.one('click', function() { // click handler
        click.resolve($this.text());
    });

    return click.then(getBookIds); // returns a promise for the ajax result
                                   // after the link has been clicked
}).toArray();

$.when.apply($, promises).then(function fancyAjax() {
     alert('alert message for fancy stuff');
});

(Demo)

【讨论】:

  • 值得一提 - 在 jQuery 中使用 $.when 和在 Bluebird 等更严肃的 Promise 库中使用 Promise.all 完成 Promise 数组的聚合。
  • @Bergi 如果我要让它尽可能灵活,我需要一个函数来接收一个 jQuery 数组(在此类锚标记中)并为每个数组创建一个 promise,然后检查每个索引的状态以查看它们是否已解决?
  • @wootscootinboogie:是的(正如我的示例代码中的 map 所做的那样),不,您不需要手动检查承诺状态。正如 Benjamin 所说,您可以使用 $.when 来聚合它们。
  • @wootscootinboogie: .one() 只执行一次处理程序,即它在不再需要时自动解除绑定(当承诺已经履行时)
  • @JohnS:不,没有缺陷。不是返回单击时解析的click 延迟,而是返回由then 构建的promise - 这是将ajax 函数链接 到解析中。这些产生的承诺与 ajax 响应一起解决。感谢您的提琴,我已经用我的代码更新了它并包含了一些日志记录:jsfiddle.net/Q7qh7/1!
猜你喜欢
  • 1970-01-01
  • 2016-08-01
  • 1970-01-01
  • 2017-10-08
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 2014-03-12
相关资源
最近更新 更多