繁体   English   中英

顺序AJAX请求处理和存储

[英]Sequential AJAX request processing and storage

我正在尝试编写脚本以从具有Web界面的打印机中顺序提取数据。 大型的本地网络上有500多个,因此,我想在上一次返回(无论成功与否)后都调用下一个的原因。 我很难绕过回调...如果这是最好的解决方案。

这就是我目前的立场(请亲爱的,这是我对jQuery / Javascript的简介,这是一个证明测试)。 另外,有没有一种方法可以根据结果调用来构建数组? 我之所以使用Javascript是因为我无法让PHP随执行时间而变化。

哦,您将在下面看到ASYNC:true,仅是因为我尝试了w / false,但它不起作用(返回任何内容)。

function pingDevice(prnList) {
    prnList = ["www.google.com", "amazon.com", "facebook.com", "as923f.com"];
    document.getElementById("myDiv").innerHTML="please wait...";

    $(prnList).each( function(index,printer) {
        $.ajax({
            type: "GET",
            dataType: "html",
            url: "pingTest.php?ping="+printer,
            async: true,
            success: function (data) {
                $('#myDiv').append( $('<div class="prn"></div>').html(data) );
                $prnResults[printer] = data;
            },
            error: function () {
                $prnResults[printer] = data;
            }
        });
    });
    $('#myDiv').append( $('<div class="prn"></div>').$prnResults );
}

您似乎希望代码执行两件事。

  1. 仅当返回前一台打印机的请求后,才请求下一台打印机的数据
  2. 仅在所有请求返回后才更新DOM。

不幸的是,你的代码既不这些事情。 :(

$.each是一种迭代类似数组的事物的方法,但它不会等到请求返回后才继续移动列表中的下一项。 Ajax请求是异步的,这意味着你给他们打电话,在你的代码移动到下一个操作。 当他们这样做,他们将回调无论是successerror的功能,但同时请求发生此代码不会阻塞。

如果要触发顺序请求,则可以创建某种帮助程序功能,该功能可以使您遍历数组,并且仅在知道第一个完成后才在数组的下一项上调用该函数。 如果要在它们全部完成后执行一些操作,则需要再执行一个函数,当数组中的所有项目都已处理完毕时,该函数将进行回调。

这是一个有关如何按顺序执行异步操作的小示例。

var data = ['1', '2', '3', '4'];

function doAsnycStuffSequentially(data, callback, final) {
  var i = 0,
      length = data.length;

  function getNextItem() {
    callback(data[i++], done);
  }

  function done(err) {
    if (err) {
      return final(err);
    }

    // Only call the final function if there is an error or if we are done looping.
    if (i >= data.length) {
      return final();
    }

    getNextItem();
  }

  getNextItem();
}

doAsyncStuffSequentially(data, function(item, done) {
  console.log("item is ", item);
  // simulate some asynchronous operation
  setTimeout(done, 1000);
}, function(err) {
  console.log("done with all and error is", err);
});

要将这种模式应用于您自己的代码,只需定义自己的回调函数,该回调函数将在数组中的每个项目上调用,如下所示:

var printerData = {},
    printerNames = ['hurp', 'durp'];

function getPrinterInfo(printerName, done) {
  $.ajax({
      type: "GET",
      dataType: "html",
      url: "pingTest.php?ping="+printer,
      success: function (data) {
        printerData[printerName] = data;
        done();
      },
      error: function (jqXHR, textStatus, err) {
        console.error("error getting printer status", err);
        done(err);
      }
  });
}

doAsyncStuffSequentially(printerName, getPrinterInfo, function(err) {
  console.log("done getting printer names and error was", err);
  console.log("printerData is", printerData);
});

关键是您要在successerror回调中调用done函数。 这标志着该doAsyncStuffSequentially是一个异步操作已完成功能,它应该要么开始下一个,或致电final功能,如果我们完成或发生错误。

尽管我同意Sonesh的观点,即服务器端的某个东西可能更适合此任务,但是这里对您的代码进行了一些调整(应该尝试)。

基本上,将实际的ajax调用嵌套在其自己的函数pingNext 每次调用返回时,都会为prnList数组中的下一项再次调用该函数。 另外,我调整了代码以对ajax调用使用jQuery的类似于promise的语法。 通常,它是链接ajax调用的一种更好的语法(尽管此处并非完全必要)

function pingDevice(prnList) {
  prnList = ["www.google.com", "amazon.com", "facebook.com", "as923f.com"];
  document.getElementById("myDiv").innerHTML="please wait...";

  var i = 0;
  function pingNext(j) {
    $.ajax({
        type: "GET",
        dataType: "html",
        url: "pingTest.php?ping="+prnList[j],
        async: true,
    }).done(function(data) {
      // stuff to do when successfull
      $('#myDiv').append( $('<div class="prn"></div>').html(data) );
    }).fail(function(data) {
      // stuff to do on error
    }).always(function(data){
      // stuff to do no matter what

      // stash the result
      $prnResults[printer] = data;

      // if there are more items in the prnList array, repeat
      if (i < prnList.length) {
        i++;
        pingNext(i);
      }
    });
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM