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

Selectize.js load callback pass-through to custom function

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

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

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

这里是要调用的"loadStates()"函数。对于这个示例,我一直保持简单,但理想情况下,这可以是任何一种方法,包括异步方法。

<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 方法不同。但是,它们的工作原理相同(期望返回数据),因此对于这个问题的目的没有真正的区别。

我在上面简化了我的代码,我会记下以后不要这样做。我还有两个可选参数,用户可以指定将数据切片为更小的 selection,指定返回数据中的键,and/or 记录限制。我想我有一个同事提供的很好的解决方案。如果有更好的方法,我将不胜感激。

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

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

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

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

您走在正确的轨道上。 selectize documentation 状态:

load(fn) - Loads options by invoking the the provided function. The function should accept one argument (callback) and invoke the callback with the results once they are available.

这里的重要部分是 selectize 不关心从何处或如何获取数据。获取数据可以同步或异步发生,因为它只关心 callback().

的参数

这一点在您的代码中有点混乱,但您仍然可以在那里看到它的作用。您的 _load() 函数通过采用回调参数来完成它应该做的事情。但是,自定义函数returns直接取其值。虽然这样做并没有错,但它会让您以错误的方式思考。

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

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

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

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

很容易将异步概念与使用回调混为一谈,但我希望这有助于澄清一点!