【问题标题】:Using jQuery when to defer ajax processing何时使用 jQuery 延迟 ajax 处理
【发布时间】:2018-01-06 06:49:45
【问题描述】:

我有一个需要按特定顺序调用的 15 个以上 ajax 请求的列表。我需要每个 ajax 调用等到前一个函数完成后再进行下一个调用。出现这个问题是因为我的 ajax 调用有一个直接回调,它也是一个 ajax 调用。

createCheckIn() {
    this.selectedList = [...] // long list of objects
    count = 0

    for ( i=0; i < this.selectedList.length; i++ ) {
        $.ajax({
            method: "POST",
            url: url,
            data: {
                check_in: {
                    client_id: this.selectClient.id,
                    program_id: this.program_id
                }
            },
            success: function(res) {
                that.createWeighIn(count, res.id)
                count = count + 1
            },
            error: function(err) {
                console.log(err)
            }
        })
    }
},
createWeighIn(index, check_in_id) {
    let data = {}
    let that = this
    data.weigh_in = this.selectedList[index]

    $.ajax({
        method: "POST",
        url: url,
        data: data,
        success: function(res) {
            console.log(res)
        },
        error: function(err) {
            console.log(err)
        }
    })
}

生成了正确的数据,但我认为排序已关闭,因为最终会在前一个条目完成之前开始调用 createCheckIn()

有没有办法链接这些函数,以便在 selectedList 迭代之前调用(并完成)createCheckIn()createWeighIn()

【问题讨论】:

标签: javascript jquery ajax


【解决方案1】:

createCheckIn() 中的 for 循环不会停止等待您的 ajax 返回。你可以这样做:

function createCheckIn(oldI, oldCount){
    var count = 0;
    var currentI = 0;
    if(oldCount != null){
      count = oldCount;
    }
    if(oldI != null){
      currentI = oldI;
    }
    if(currentI < this.selectedList.length){
      $.ajax({
          method: "POST",
          url: url,
          data: {
              check_in: {
                  client_id: this.selectClient.id,
                  program_id: this.program_id
              }
          },
          success: function(res) {
              that.createWeighIn(count, res.id)
              createCheckIn(currentI + 1, count + 1);
          },
          error: function(err) {
              console.log(err)
          }

      }); //ajax
    }  // if
}

您似乎也可以消除其中一个计数器,icount

【讨论】:

    【解决方案2】:

    似乎这遗漏了一些潜在的非常重要的细节,这些细节涉及到您需要做什么(即this.selectedItems generation)以及之后会发生什么(如果一个调用签入失败怎么办,如果签入成功但它的相应的称重失败等)。那就是……

    除了引用已有的数据之外,您似乎实际上并没有将计数器用于其他任何事情,所以为什么不直接将其传递给:

    createWeighIn(weighInData, check_in_id) {
        let data = {};
        let that = this;
        data.weigh_in = weighInData;
        // ... your other code
    }
    

    我会让createCheckIn 只处理执行ajax 请求并在您的系统中进行单个“保留”。然后我会创建一个名为checkIn 的新方法,它使用前两种方法来处理所有选定的项目:

    checkIn() {
        let self = this;
        let promises = [];
        let this.selectedList = [...];
    
        for (let = 0; i < this.selectedList.length; i++) {
            // always create the deferred outside the call
            let def = $.Deferred();
            promises.push(def.promise());
    
            this.createCheckIn().done(function (res) {
                self.createWeighIn(self.selectedList[i], res.id))
                    .done(function () {
                        // resolve
                        def.resolve.apply(def, Array.prototype.slice.call(arguments);
                    })
                    .fail(function () {
                        def.reject.apply(def, Array.prototype.slice.call(arguments);
                    });
            }).fail(function () {
               // if checkin fails, always reject because we know weighIn wont be called
               def.reject.apply(def, Array.prototype.slice.call(arguments);
            });
        };
    
        // this will resolve/fail when all promises (from createWeighIn) resolve/fail
        return $.when.apply(null, promises);
    }
    

    所以把它们放在一起:

    {
        createCheckIn() {
            let request = $.ajax({
                    method: "POST",
                    url: url,
                    data: {
                        check_in: {
                            client_id: this.selectClient.id,
                            program_id: this.program_id
                        }
                    }
                })
                .fail(function(err) {
                    console.log(err)
                });
            };
    
            return request;
        },
        createWeighIn(data, check_in_id) {
            let params = {};
    
            params.weigh_in = data;
    
            let request = $.ajax({
                method: "POST",
                url: url,
                data: params,
                success: function(res) {
                    console.log(res)
                },
                error: function(err) {
                    console.log(err)
                }
            });
    
            return request;
        },
    
        checkIn() {
            let self = this;
            let promises = [];
            let this.selectedList = [...];
    
            for (let = 0; i < this.selectedList.length; i++) {
                // always create the deferred outside the call
                let def = $.Deferred();
                promises.push(def.promise());
    
                this.createCheckIn().done(function (res) {
                    self.createWeighIn(self.selectedList[i], res.id))
                        .done(function () {
                            // resolve
                            def.resolve.apply(def, Array.prototype.slice.call(arguments);
                        })
                        .fail(function () {
                            def.reject.apply(def, Array.prototype.slice.call(arguments);
                        });
                }).fail(function () {
                   // if checkin fails, always reject because we know weighIn wont be called
                   def.reject.apply(def, Array.prototype.slice.call(arguments);
                });
            };
    
            // this will resolve/fail when all promises (from createWeighIn) resolve/fail
            return $.when.apply(null, promises);
        }
    }
    

    【讨论】:

    • 我最终使用了 Promise 和一些递归来解决它。但是这个话题对我来说很新,所以我可能犯了一些错误。我将其作为答案提交,以防它帮助人们下线
    【解决方案3】:

    我最终引入了 Promise,以及一些递归并完全移除了循环。我基本上是通过使用索引为 0 调用 createCheckIn() 来开始这个过程的:

    this.createCheckIn(0)
    
    createCheckIn(index) {
        this.selectedList = [...] // long list of objects
        count = 0
    
        let prom = new Promise(function(resolve, reject) {
            $.ajax({
                method: "POST",
                url: url,
                data: {
                    check_in: {
                        client_id: that.selectClient.id,
                        program_id: that.program_id
                    }
                },
                success: function(res) {
                    resolve(that.createWeighIn(index, res.id))
                },
                error: function(err) {
                    reject(console.log(err))
                }
            })
        })
    },
    createWeighIn(index, check_in_id) {
        let data = {}
        let that = this
        data.weigh_in = this.selectedList[index]
    
        let prom = new Promise(function(resolve, reject) {
            $.ajax({
                method: "POST",
                url: url,
                data: data,
                success: function(res) {
                    console.log(res)
                    if ( index == (that.selectedList.length - 1) ) {
                        that.complete = true
                        resolve(console.log("complete"))
                    } else {
                        index++
                        resolve(that.createCheckIn(index))
                    }
                },
                error: function(err) {
                    console.log(err)
                }
            })
        })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      • 2013-06-10
      • 2013-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多