Selectize.js将回调传递加载到自定义函数

时间:2015-06-06 00:18:33

标签: javascript jquery asynchronous callback selectize.js

我已配置selectize.js以从html数据属性收集配置选项。我的一种配置类型是能够指定一个js函数来调用自定义数据加载(在简单的ajax加载之外)。代码运行良好,直到我运行异步的自定义函数。使用异步方法时,selectize.js加载回调在数据加载之前返回。我一直在努力寻找一种方法将selectize.js load()回调传递给自定义加载函数。

这是一个配置为运行" loadStates()"的选择元素。函数获取此特定选择元素的数据:

<select
    id="state"
    class="selectize"
    data-load-type="callback"
    data-load-callback="loadStates"
>

这是&#34; loadStates()&#34;要调用的函数。我对这个例子保持简单,但理想情况下,这可以是任何一种方法,包括异步方法。

<script>
    function loadStates(searchQuery) {
        return {
            "states": [
                {
                    "id": 1,
                    "abbr": "AK",
                    "description": "Alaska"
                },
                {
                    "id": 2,
                    "abbr": "CA",
                    "description": "California"
                },
                {
                    "id": 3,
                    "abbr": "OR",
                    "description": "Oregon"
                },
                {
                    "id": 4,
                    "abbr": "WA",
                   "description": "Washington"
                }
            ]
        };
    }
</script>

最后,这是我的匿名函数被传递给selectize.js加载方法。

// Get custom load function from select element data attribute
var loadCallback = $(this).attr('data-load-callback');

// The selectize.js load option needs an anonymous function with two
// arguments, query and callback. This function should return the data.
var _load = function(query, callback) {

    // Call the custom load function
    callback(window[loadCallback](query));
};

// Pass the _load configuration to selectize
$(this).selectize({load: _load});

这一切都适用于简单的loadStates()函数。但是,只要我添加异步内容,就会很快返回selectize.js load()回调。

我尝试了什么:

我尝试将load()回调函数发送到自定义函数中,如下所示:

// ...

// Call the custom load function
window[loadCallback](query, callback);

// ...

function loadStates(searchQuery, callback) {
    callback( 
        // ... json data here
    );
}

但是,没有返回任何数据。

更新 - 使用@thewildpendulum解决方案:

因此,这个load选项具有selectize,这与load()API方法不同。但是,它们的工作方式相同(期望返回数据),因此对于此问题的目的没有真正的区别。

我上面的代码有点简化了,我将会做一个注释,以便将来不要这样做。我还有两个可选参数,用户可以指定这些参数将数据切片为较小的选项,指定返回数据中的键和/或记录限制。我想我有一个很好的解决方案,由同事提供。如果有更好的方法,我将不胜感激。

建议的新回调对象,添加两个加载参数属性

// callbacks object for custom user provided data methods
var callbacks = {
    loadKey:    null,
    loadLimit:  0,
    loadStates: function (query, selectizeCallback) {
      var data = {
        "states": [
          {
            "id": 1,
            "abbr": "AK",
            "description": "Alaska"
          },
          {
              "id": 2,
              "abbr": "CA",
              "description": "California"
          },
          {
              "id": 3,
              "abbr": "OR",
              "description": "Oregon"
          },
          {
              "id": 4,
              "abbr": "WA",
              "description": "Washington"
          }
        ]
      };
      if (null !== this.loadKey) {
        selectizeCallback(data[this.loadKey].slice(0, this.loadLimit));
      }
      else {
        selectizeCallback(data.slice(0, this.loadLimit));
      }
    }
  }

使用用户回调对象和自定义数据切片构建选择性加载选项的新代码

// Set load parameters (gather these values from html data attr earlier)
callbacks.loadKey   = loadKey;
callbacks.loadLimit = loadLimit;

// Build load option
var _load = callbacks[loadCallback].bind(callbacks);

1 个答案:

答案 0 :(得分:2)

你走在正确的轨道上。 selectize documentation州:

  

load(fn) - 通过调用提供的函数加载选项。该函数应该接受一个参数(回调),并在结果可用后调用回调。

这里的重要部分是选择不关心数据的获取位置和方式。获取数据可以同步或异步进行,因为它所关心的只是callback()的参数。

这一点在您的代码中有点混乱,但您仍然可以在那里看到它。您的_load()函数完全按照回调参数执行的操作。但是,自定义函数直接返回其值。虽然这样做没有错,但它会让你思路错误。

// Get custom load function from select element data attribute
var loadCallbackSync = $(this).attr('data-load-callback');

// we have this wrapper function that calls our custom load function
var _load = function(query, callback) {
    var result = window[loadCallbackSync](query);
    // -> returns our result

    callback( result );
};

// if we take the same approach with async loading...
var loadCallbackAsync = $(this).attr('data-load-callback');

var _load = function(query, callback) {
    var result = window[loadCallbackAsync](query);
    // -> oh noes!

    callback( result );
};

尽管使用return的同步函数callback()的数据和异步函数的常见模式,我们真正需要做的就是将数据转换为selectize的回调函数。事实证明,您根本不需要_load()。您可以简单地编写自定义函数,以便通过选择直接使用它们。

(我无法在选择接受load()参数的query函数中找到任何引用。但是,包括它或删除是微不足道的。)

var callbacks = {
    loadStatesSync: function (query, selectizeCallback) {
        var states = [
            // ...
        ];
        var result = doSomethingWithQuery(states, query);

        selectizeCallback(result);
    },
    loadStatesAsync: function (query, selectizeCallback) {
        $.ajax({
            // do something with query...,
            success: function (result) {
                selectizeCallback(result);
            }
        });
    }
}

var fnName = $(this).data('load-callback');
var _load  = callbacks[fnName];

$(this).selectize({load: _load});

使用回调很容易让异步概念混淆,但我希望这有助于清除这一点!