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

Selectize.js load callback pass-through to custom function

本文关键字:自定义函数 加载 回调 js      更新时间:2023-09-26

我已经配置了select .js来从html数据属性中收集配置选项。我的配置类型之一是能够指定一个js函数来调用自定义数据加载(在简单的ajax加载之外)。代码工作得很好,直到我运行一个异步的自定义函数。使用异步方法时,select .js的load回调函数会在加载数据之前返回。我一直在努力寻找一种方法来通过select .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()函数一起工作得很好。然而,一旦我添加了一些异步的东西,select .js的load()回调就会很快返回。

我试过了:

我尝试像这样发送load()回调到自定义函数:

// ...
// Call the custom load function
window[loadCallback](query, callback);
// ...
function loadStates(searchQuery, callback) {
    callback( 
        // ... json data here
    );
}

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

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

所以有这个加载选项与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);

你做对了。选择文档说明:

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

这里重要的部分是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 );
};

尽管同步函数return使用它们的数据和异步函数使用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});

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