简体   繁体   English

顺序AJAX请求处理和存储

[英]Sequential AJAX request processing and storage

I'm trying to write a script to sequentially pull data from printers that have a web interface. 我正在尝试编写脚本以从具有Web界面的打印机中顺序提取数据。 There are over 500 on a large local network, hence the reason I'd like to call out to the next one once the previous returns (successful or not). 大型的本地网络上有500多个,因此,我想在上一次返回(无论成功与否)后都调用下一个的原因。 I'm having difficulties wrapping my head around callbacks ...if that's the best solution. 我很难绕过回调...如果这是最好的解决方案。

Here's where I currently stand (be kind, this is my intro to jQuery/Javascript and this is a proof test). 这就是我目前的立场(请亲爱的,这是我对jQuery / Javascript的简介,这是一个证明测试)。 Also, is there a way to build an array from the resulting calls? 另外,有没有一种方法可以根据结果调用来构建数组? The reason I've turned to Javascript is that I could not get PHP to behave with the execution times. 我之所以使用Javascript是因为我无法让PHP随执行时间而变化。

Oh, you'll see ASYNC: true below only because I tried w/ false and it did not work (return anything). 哦,您将在下面看到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 );
}

It looks like there are two things you want your code to do. 您似乎希望代码执行两件事。

  1. Only request data for the next printer when the request for the previous printer has returned 仅当返回前一台打印机的请求后,才请求下一台打印机的数据
  2. Only update the DOM once all the requests have returned. 仅在所有请求返回后才更新DOM。

Unfortunately, the code you have does neither of these things. 不幸的是,你的代码既不这些事情。 :( :(

$.each is a way to iterate over an array-like thing, but it won't wait until the request returns before moving on the next item in the list. $.each是一种迭代类似数组的事物的方法,但它不会等到请求返回后才继续移动列表中的下一项。 The ajax requests happen asynchronously, which means you call them and move on to the next operation in your code. Ajax请求是异步的,这意味着你给他们打电话,在你的代码移动到下一个操作。 When they are done, they will call back either the success or error functions, but this code will never block while requests are happening. 当他们这样做,他们将回调无论是successerror的功能,但同时请求发生此代码不会阻塞。

If you want to fire off sequential requests, you can create some kind of helper function that lets you loop through an array, and only calls the function on the next item in the array when you know you are done with the first one. 如果要触发顺序请求,则可以创建某种帮助程序功能,该功能可以使您遍历数组,并且仅在知道第一个完成后才在数组的下一项上调用该函数。 If you want to do some action when they are all finished, then you need one more function that calls back when all the items in the array are done being processed. 如果要在它们全部完成后执行一些操作,则需要再执行一个函数,当数组中的所有项目都已处理完毕时,该函数将进行回调。

Here is a small example of how you can do asynchronous things in sequence. 这是一个有关如何按顺序执行异步操作的小示例。

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);
});

To apply this pattern to your own code, you just define your own callback function that gets called on each item in the array, like this: 要将这种模式应用于您自己的代码,只需定义自己的回调函数,该回调函数将在数组中的每个项目上调用,如下所示:

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);
});

The key is that you are calling the done function in the success and error callbacks. 关键是您要在successerror回调中调用done函数。 This signals to the doAsyncStuffSequentially function that an async operation has finished, and it should either start the next one or call the final function if we are done or an error occurred. 这标志着该doAsyncStuffSequentially是一个异步操作已完成功能,它应该要么开始下一个,或致电final功能,如果我们完成或发生错误。

though i agree with Sonesh's sentiment that something server-side would probably be better suited to this task, here's a few tweaks to your code that should work (untested). 尽管我同意Sonesh的观点,即服务器端的某个东西可能更适合此任务,但是这里对您的代码进行了一些调整(应该尝试)。

basically, nest the actual ajax call in its own function pingNext . 基本上,将实际的ajax调用嵌套在其自己的函数pingNext each time a call comes back in, the function is called again for the next item in the prnList array. 每次调用返回时,都会为prnList数组中的下一项再次调用该函数。 Also, i tweaked the code to use jQuery's promise-like syntax for ajax calls. 另外,我调整了代码以对ajax调用使用jQuery的类似于promise的语法。 it is, in general, a much nicer syntax for chaining ajax calls (though not entirely necessary here) 通常,它是链接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