使用循环时的JavaScript回调函数

时间:2016-01-23 16:18:51

标签: javascript

以下代码的作用如下:

  • 转到数据库中的表并检索我将发送给Google API的一些搜索条件(PHP文件为getSearchSon.php)

  • 获得结果后,我想绕过它,调用Google API(searchCriteriasFuc)并将结果存储在数组中

  • 代码的最后一部分是使用Google API(updateSearchDb.php)返回的结果对两个不同的表进行更新

在我的代码中,我在一些我不喜欢的场合使用setTimeout。而不是使用setTimeout,我想以更有效的方式正确使用回调函数(这可能是我的问题的原因)我这样做的最佳方式是什么?

$(document).ready(function() {


    $.ajax({ 

        url: 'getSearchSon.php',  

        type: 'POST',

        async: true,

        dataType: 'Text',

        /*data: { }, */

        error: function(a, b, c) { alert(a+b+c); }  

    }).done(function(data) {


    if(data != "connection")
    {
        var dataSent = data.split("|");

        var search_criterias = JSON.parse(dataSent[0]);

        var date_length = dataSent[1];

        var divison_factor = dataSent[2];

        var length = search_criterias.length;

        var arrXhr = [];

        var totalResultsArr = [];

        var helperFunc = function(arrayIndex)
        {
            return function()
            {
                var totalResults = 0;

                if (arrXhr[arrayIndex].readyState === 4 && arrXhr[arrayIndex].status == 200) 
                {
                    totalResults = JSON.parse(arrXhr[arrayIndex].responseText).queries.nextPage[0].totalResults;

                    totalResultsArr.push(totalResults);
                }
            }
        }

        var searchCriteriasFuc = function getTotalResults(searchParam, callback) 
        {   
            var searchParamLength = searchParam.length;

            var url = "";

            for(var i=0;i<searchParamLength;i++)
            {
                url = "https://www.googleapis.com/customsearch/v1?q=" + searchParam[i] + "&cx=005894674626506192190:j1zrf-as6vg&key=AIzaSyCanPMUPsyt3mXQd2GOhMZgD4l472jcDNM&dateRestrict=" + date_length;

                arrXhr[i] = new XMLHttpRequest();

                arrXhr[i].open("GET", url, true);

                arrXhr[i].send();

                arrXhr[i].onreadystatechange = helperFunc(i);
            }

            setTimeout(function()
            {       
                if (typeof callback == "function")  callback.apply(totalResultsArr);
            }, 4000);


            return searchParam;
        }   

        function callbackFunction()
        { 
            var results_arr = this.sort();

            var countResultsArr = JSON.stringify(results_arr);

            $.ajax({

                url: 'updateSearchDb.php',  

                type: 'POST',

                async: true,

                dataType: 'Text',

                data: { 'countResultsArr': countResultsArr },

                error: function(a, b, c) { alert(a+b+c); }  

            }).done(function(data) {

                var resultsDiv = document.getElementById("search");

                if(data == "NORECORD") resultsDiv.innerHTML = 'Updated failed. There was a problem with the database';

                else resultsDiv.innerHTML = 'Update was successful';

            }); //end second ajax call
        }

        //llamando funcion principal
        var arrSearchCriterias = searchCriteriasFuc(search_criterias, callbackFunction);

    }
    else
    {
        alert("Problem with MySQL connection.");
    }

    }); // end ajax 

});

3 个答案:

答案 0 :(得分:2)

你是如何在2015年完成的

回调是过去的事情。现在,您使用Promise来表示异步任务的结果值。这是一些未经测试的代码:

$(document).ready(function() {
  $.ajax({ 
      url: 'getSearchSon.php',  
      type: 'POST',
      async: true,
      dataType: 'text'
      /*data: { }, */
  }).then(function(data) {
    if (data == 'connection') {
      alert("Problem with MySQL connection.");
    } else {
      var dataSent = data.split("|");
      var search_criterias = JSON.parse(dataSent[0]);
      var date_length = dataSent[1];
      var divison_factor = dataSent[2];

      return Promise.all(search_criterias.map(function(criteria) {
        return $.ajax({
          url: "https://www.googleapis.com/customsearch/v1"
            + "?q=" + criteria 
            + "&cx=005894674626506192190:j1zrf-as6vg"
            + "&key=AIzaSyCanPMUPsyt3mXQd2GOhMZgD4l472jcDNM"
            + "&dateRestrict=" + date_length,
          type: 'GET'
        });
      })).then(function(totalResultsArr) {
        totalResultsArr.sort();
        var countResultsArr = JSON.stringify(totalResultsArr);

        return $.ajax({
          url: 'updateSearchDb.php',  
          type: 'POST',
          async: true,
          dataType: 'text',
          data: { 'countResultsArr': countResultsArr },
          error: function(a, b, c) { alert(a+b+c); }  
        });
      }).then(function(data) {
        var resultsDiv = document.getElementById("search");
        if(data == "NORECORD") {
          resultsDiv.innerHTML = 'Updated failed. There was a problem with the database';
        } else {
          resultsDiv.innerHTML = 'Update was successful';
        }
      });
    }
  }).then(null, function() {
    alert('Some unexpected error occured: ' + e);
  });
});

2016年这是你做的(ES7)

您可以使用async / await。

$(document).ready(async() => {
  try {
    var data = await $.ajax({ 
        url: 'getSearchSon.php',  
        type: 'POST',
        async: true,
        dataType: 'text'
        /*data: { }, */
    });
    if (data == 'connection') {
      alert("Problem with MySQL connection.");
    } else {
      var dataSent = data.split("|");
      var search_criterias = JSON.parse(dataSent[0]);
      var date_length = dataSent[1];
      var divison_factor = dataSent[2];

      var totalResultsArr = await Promise.all(
        search_criterias.map(criteria => $.ajax({
          url: "https://www.googleapis.com/customsearch/v1"
          + "?q=" + criteria 
          + "&cx=005894674626506192190:j1zrf-as6vg"
          + "&key=AIzaSyCanPMUPsyt3mXQd2GOhMZgD4l472jcDNM"
          + "&dateRestrict=" + date_length,
          type: 'GET'
        }))
      );

      totalResultsArr.sort();
      var countResultsArr = JSON.stringify(totalResultsArr);
      var data2 = await $.ajax({
          url: 'updateSearchDb.php',  
          type: 'POST',
          async: true,
          dataType: 'text',
          data: { 'countResultsArr': countResultsArr },
          error: function(a, b, c) { alert(a+b+c); }  
      });
      if(data2 == "NORECORD") {
        resultsDiv.innerHTML = 'Updated failed. There was a problem with the database';
      } else {
        resultsDiv.innerHTML = 'Update was successful';
      }
    }
  } catch(e) {
    alert('Some unexpected error occured: ' + e);
  }
});

2016年更新

不幸的是async/await提案最终没有达到ES7规范,所以它仍然是非标准的。

答案 1 :(得分:0)

要在Google调用完成后执行回调,您可以更改:

    var requestCounter = 0;        

    var helperFunc = function(arrayIndex)
    {
        return function()
        {
            if (arrXhr[arrayIndex].readyState === 4 && arrXhr[arrayIndex].status == 200) 
            {
                requestCounter++;                    

                totalResults = JSON.parse(arrXhr[arrayIndex].responseText).queries.nextPage[0].totalResults;

                totalResultsArr.push(totalResults);

                if (requestCounter === search_criterias.length) {
                    callbackFunction.apply(totalResultsArr);
                }
            }
        }
    }

然后删除searchCreteriaFuc上的setTimeout。

考虑使用promises和Promise.all来更清洁:D

答案 2 :(得分:0)

你可以在下面的事情中重新格式化你的getTotalResults函数,然后它会搜索相当顺序,但它也应该通过额外的回调来返回结果。

'use strict';

function getTotalResults(searchParam, callback) {
  var url = "https://www.googleapis.com/customsearch/v1?q={param}&cx=005894674626506192190:j1zrf-as6vg&key=AIzaSyCanPMUPsyt3mXQd2GOhMZgD4l472jcDNM&dateRestrict=" + (new Date()).getTime(),
    i = 0,
    len = searchParam.length,
    results = [],
    req, nextRequest = function() {
      console.log('received results for "' + searchParam[i] + '"');
      if (++i < len) {
        completeRequest(url.replace('{param}', searchParam[i]), results, nextRequest);
      } else {
        callback(results);
      }
    };
  
  completeRequest(url.replace('{param}', searchParam[0]), results, nextRequest);
}

function completeRequest(url, resultArr, completedCallback) {
  var req = new XMLHttpRequest();

  req.open("GET", url, true);
  req.onreadystatechange = function() {
    if (this.readyState === 4 && this.status == 200) {
      var totalResults = JSON.parse(this.responseText).queries.nextPage[0].totalResults;
      resultArr.push(totalResults);
      completedCallback();
    }
  };
  req.send();
}

getTotalResults(['ford', 'volkswagen', 'citroen', 'renault', 'chrysler', 'dacia'], function(searchResults) {
  console.log(searchResults.length + ' results found!', searchResults);
});

但是,由于您已经在代码中使用了JQuery,因此您还可以构造所有请求,然后使用JQuery.when功能,如本问题中所述

Wait until all jQuery Ajax requests are done?