Typeahead - 无法使用动态创建的数组作为数据源

Typeahead - Unable to use dynamically created array as source of data

我有一个 json 文件,其中包含国家和每个国家的城市,结构如下:

{
  "United States": [
    "New York",
    "Los Angeles",
    "San Francisco",
    "Baltimore",
    "Washington"
  ],
  "England": [
    "Manchester",
    "Liverpool",
    "Newcastle",
    "Bradford",
    "London"
  ]
}

在页面加载时,我提取国家并将它们推入 array。在 select 国家/地区,我根据 selected 国家/地区创建了 array 个城市。该代码适用于预定义的 array,但不适用于新创建的代码。有什么想法吗?

Jsfiddle here

HTML:

<div id="countryContainer">
    <label>Heroes from country:</label>
    <select multiple="multiple" data-placeholder="Select a country" id="countryList"></select>
</div>
<br><br>
<input type="text" id="search">

JS代码有点长:

    $(document).ready(function () {
        var source = [];
        $.ajax({
            url: "https://api.myjson.com/bins/22mnl",
            dataType: "json",
            success: function (response) {
                response1 = response;

                var keys = Object.keys(response);
                keys.forEach(function (key) {
                    source.push(key);
                });
                console.log(source);
                for (var i = 0; i < source.length; i++) {
                    var option1 = $('<option value=' + source[i] + '>' + source[i] + '</option>');
                    $("#countryList").append(option1);
                }
            }
        });
    });

    $('#countryList').select2();
    var citiesArray = [];
    var citiesObjArr = [];

    //creation of array of countries from the json
    $("#countryList").on("change", function () {
        if ($("#countryContainer li").length > 1) {
            console.log("changed");
            var selectedCountry = $("#countryList option:selected")[0].innerHTML;
            console.log("country selected: " + selectedCountry);
            citiesObjArr.length = 0;
            citiesArray.length = 0;
            createArrayOfCities(selectedCountry);
        } else {
            console.log("empty");
        }
    });

    //extraction of cities per selected country from the original json and insertion into an array of objects
    function createArrayOfCities(key) {
        $.ajax({
            url: "https://api.myjson.com/bins/22mnl",
            dataType: "json",
            success: function (response) {
                if (response.hasOwnProperty(key)) {
                    var j = 0;
                    var i = 0;
                    response[key].forEach(function (i) {
                        citiesArray[j] = i;
                        //CREATION OF THE CITIES OBJECTS ARRAY
                        citiesObjArr.push({
                            val: i
                        });
                        j++;
                    });
                }
                console.log(citiesObjArr);
                console.log(typeof (citiesObjArr));
            }
        });
    }

    //typeahead autocomplete here

//THIS ARRAY OF OBJECTS WORK, BUT citiesObjArr DOES NOT. WHY??

/*
    var data1 = [{
        val: "city1111"
    }, {
        val: "city2222",
    }];
    */

    var titles = new Bloodhound({
        datumTokenizer: function (data) {
            return Bloodhound.tokenizers.whitespace(data.val);
        },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        local: citiesObjArr
    });
    titles.initialize();
    $("#search").typeahead({
        highlight: true
    }, {
        name: 'titles',
        displayKey: 'val',
        source: titles.ttAdapter()
    });

这里的问题是您在成功回调之外失去了对 citiesObjArr 的访问权限。要解决此问题,您可以 defer 您的响应对象:

在您的 change 处理程序中,您可以执行以下操作:

$.when(createArrayOfCities())
  .then(function(data) {
      // Pass in the response and selected country to a new function
      handleResponse(data, selectedCountry);
   });

您需要将 createArrayOfCities() 函数更改为以下内容:

function createArrayOfCities() {
  return $.ajax({
      url: "https://api.myjson.com/bins/22mnl",
      dataType: "json",
      success: function (response) {
          return response;
      }
  });
}

注意:您可能需要更改上述函数的名称以提高可读性(因为它不再构建城市数组)

然后你可以调用新的handleResponse函数:

function handleResponse(response, key) {

  if (response.hasOwnProperty(key)) {
    var j = 0;
    var i = 0;
    response[key].forEach(function (i) {
       citiesArray[j] = i;
       ////CREATION OF THE CITIES OBJECTS ARRAY
       citiesObjArr.push({
          val: i
       });
       j++;
    });
  };

  var titles = new Bloodhound({
    datumTokenizer: function (data) {
        return Bloodhound.tokenizers.whitespace(data.val);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    local: citiesObjArr
  });

  titles.initialize();
  $("#search").typeahead({
    highlight: true
  }, {
    name: 'titles',
    displayKey: 'val',
    source: titles.ttAdapter()
  });

}

Here is your updated Fiddle