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

标签 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"
>

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

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

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

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

最佳答案

你走在正确的道路上。 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() 函数通过接受回调参数来完成它应该做的事情。但是,自定义函数会直接返回其值。虽然这样做并没有错,但它会让你以错误的方式思考。

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

尽管同步函数返回数据的常见模式和使用callback()的异步函数不同,但我们真正需要做的就是将数据获取到 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});

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

关于javascript - Selectize.js 加载回调传递到自定义函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30677611/

相关文章:

jquery - 使用 jQuery 设置下拉列表的选定索引

javascript - 模块异步函数中的变量范围

c# - 使用异步套接字方法时延迟

javascript - 使用其上下文调用原始回调函数

javascript - jQuery onload - .load() - 事件不适用于动态加载的 iframe

java - IPv4、IPv6 和主机名正则表达式

javascript - 一个接一个改变多个div的颜色

php - 从 php 到 javascript 的 json 对象分配有什么问题?

jquery - 基于元素高度滚动使用 jquery 添加/删除类?

node.js - 异步 : Bypass a function in a waterfall chain