【问题标题】:Jquery Ajax prevent fail in a deferred sequential loopJquery Ajax 防止延迟顺序循环中的失败
【发布时间】:2015-03-23 17:48:46
【问题描述】:

所以,我将顺序 ajax 链接在一起,以按顺序加载 url 数组。最初我使用.then() 而不是.always(),无论哪种方式都可以正常工作-前提是所有网址都存在。但是,由于存在丢失文件的可能性,我想弥补这一点,然后最后通知用户哪些文件丢失了,以便更容易纠正。

但是,问题在于,在丢失的文件/404 上,代码按原样执行,但随后退出循环,阻止了任何进一步的 ajax 调用。所以我想,我需要某种方式来处理fail() 并强制成功,或者以其他方式覆盖 404 上的默认行为,以便它继续通过循环进行。

不幸的是,与 Google 最接近的结果是如何反其道而行之(在成功中强制失败)。

var missing=[];
uLoadList.reduce(function(prev, cur, index) {
    return prev.then(function(data) {
        return $.ajax("/wiki/"+cur).always(function(data) {
            var temp = $('#mw-content-text',data);
            temp = $('pre',temp);
            if(temp.length > 0)
            {
                //handle success
            }else{
                //handle failure
                missing.push(cur);
            }
        });
    });
}, $().promise()).done(function() {
    if(missing.length > 0)
    {
        //notify of missing objects
    }
    //continue on.
});

最后一点,为了减轻混淆:URL 和脚本本身都在 MediaWiki 站点上 - 所以即使返回 404,也总会有页面内容,并且将包含 id 为 " mw-内容-文本”。

【问题讨论】:

    标签: javascript jquery ajax


    【解决方案1】:

    试试

    (function ($) {
        $.when.all = whenAll;
        function whenAll(arr) {
            "use strict";
            var deferred = new $.Deferred(),
                args = !! arr 
                       ? $.isArray(arr) 
                         ? arr 
                         : Array.prototype.slice.call(arguments)
                           .map(function (p) {
                             return p.hasOwnProperty("promise") 
                             ? p 
                             : new $.Deferred()
                               .resolve(p, null, deferred.promise())
                           }) 
                       : [deferred.resolve(deferred.promise())],
                promises = {
                    "success": [],
                      "error": []
                }, doneCallback = function (res) {
                    promises[this.state() === "resolved" 
                             || res.textStatus === "success" 
                             ? "success" 
                             : "error"].push(res);
                    return (promises.success.length 
                           + promises.error.length) === args.length 
                           ? deferred.resolve(promises) 
                           : res
                }, failCallback = function (res) {
                    // do `error` notification , processing stuff
                    // console.log(res.textStatus);
                    promises[this.state() === "rejected" 
                            || res.textStatus === "error" 
                            ? "error" 
                            : "success"].push(res);
                    return (promises.success.length 
                           + promises.error.length) === args.length 
                           ? deferred.resolve(promises) 
                           : res
                };
            $.map(args, function (promise, index) {
                return $.when(promise).always(function (data, textStatus, jqxhr) {
                    return (textStatus === "success") 
                        ? doneCallback.call(jqxhr, {
                            data: data,
                            textStatus: textStatus 
                                        ? textStatus 
                                        : jqxhr.state() === "resolved" 
                                          ? "success" 
                                          : "error",
                            jqxhr: jqxhr
                          }) 
                        : failCallback.call(data, {
                            data: data,
                            textStatus: textStatus,
                            jqxhr: jqxhr
                          })
                })
            });
            return deferred.promise()
        };
    }(jQuery));
    // returns `Object {
    //                   success: Array[/* success responses*/], 
    //                   error: Array[/* error responses */]
    //          }`
    

    // e.g.,
    var request = function (url, data) {
        return $.post(url, {
            json: JSON.stringify(data)
        })
    }, settings = [
        ["/echo/json/", "success1"], // `success`
        ["/echo/jsons/", "error1"], // `error`
        ["/echo/json/", "success2"], // `success`
        ["/echo/jsons/", "error2"], // `error`
        ["/echo/json/", "success3"] // `success`
    ];
    
    $.when.all(
      $.map(settings, function (p) {
        return request.apply($, p)
      })
    )
    .then(function (data) {
        console.log(data);
        // filter , process responses
        $.each(data, function(key, value) {
            if (key === "success") {
              results.append(
                  "\r\n" + key + ":\r\n" + JSON.stringify(value, null, 4)
              )
            } else {            
              results.append(
                  "\r\n" + key + ":\r\n" 
                  + JSON.stringify(
                      value.map(function(v, k) {
                        v.data.responseText = $(v.data.responseText)
                          .filter("title, #summary, #explanation")
                          .text().replace(/\s+/g, " ");
                        return v
                      })
                    , null, 4)
              )
            }
        })
    }, function (e) {
        console.log("error", e)
    });
    

    jsfiddle http://jsfiddle.net/guest271314/620p8q8h/

    【讨论】:

    • 嵌套三元组 !!a ? b ? c : d : e 可以重新排列以减少混淆,!a ? e : b ? c : d
    • @Roamer-1888 流程args = !! arr // if arguments ? $.isArray(arr) // are arguments an array ? arr // return array : Array.prototype.slice.call(arguments).map(function (p) {return p.hasOwnProperty("promise") // is p jQuery promise ? p // return jQuery promise : new $.Deferred().resolve(p, null, deferred.promise()) // else return p as resolved jQuery promise } ) // else return array of promises : [deferred.resolve(deferred.promise())] // else return deferred.promise() as array
    • 当然可以,但是应用我的重新排列,你最终会得到一个更传统、更易读的版本,args = !arr ? [deferred.resolve(deferred.promise())] : $.isArray(arr) ? arr : Array.prototype.slice.call(arguments).map(function (p) { return p.hasOwnProperty('promise') ? p : new $.Deferred().resolve(p, null, deferred.promise()); });
    • @Roamer-1888 不确定 “更传统”“更易读” 的含义?两者都可以基于感知、预先确定的偏好;还是主观的?如果感觉用上述三元模式组合js 会导致js 出现“更传统”或“更易读”,是的,使用该特定模式进行组合。 fwiw,在这里没有注意到实质性差异,建议使用三元模式来“更具可读性”;从头开始组成js,没有“约定”。两种模式似乎都返回相同的结果jsfiddle.net/guest271314/620p8q8h/5
    • 这不是什么大问题。正如你所说,这两个版本给出了相同的结果。
    猜你喜欢
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 2012-09-19
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    相关资源
    最近更新 更多