【问题标题】:How to provide an XMLHttpRequest promise to a JavaScript function如何向 JavaScript 函数提供 XMLHttpRequest 承诺
【发布时间】:2020-11-14 20:59:57
【问题描述】:

https://www.npmjs.com/package/bootstrap-4-autocomplete 上使用一个自动完成插件,并且以下工作:

$('#id').autocomplete({
    source: {'test1':1, 'test2':2, 'test1':3}
});

需要创建一个 XMLHttpRequest 而不是本地 JSON,并且正在考虑类似以下内容,虽然我没有收到错误,但我也没有得到任何东西:

$('#id').autocomplete({
    source: function() {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                return JSON.parse(this.responseText);
            }
        };
        xhttp.open(method, url, true);
        xhttp.send();
    }
});

该插件的作者不久前做了以下remark

我没有计划直接调用库中的任何 url。你什么 可以做的是在您的 ajax 调用后将自动完成设置为您的文本字段 返回,你可以用 jQuery 来做,像这样:

$.ajax('myurl').then((data) => $('#myTextfield').autocomplete({ 来源:数据}));

您不必担心将自动完成设置为多个字段 有时,当您需要更改 来源。

尝试过,正如预期的那样,$.ajax() 在页面加载时发起了一个 XMLHttpRequest 请求,而不是当用户在搜索输入中输入字符时所期望的。

如何创建 XMLHttpRequest 以将数据导入插件?我假设我应该使用 Promise,但是,如果没有,仍然会感谢任何帮助。

谢谢

【问题讨论】:

    标签: javascript jquery promise xmlhttprequest


    【解决方案1】:

    嗯,插件应该是这样工作的。它的肉和土豆是 createItems 函数,在 keyup 事件上调用 - 并负责用项目填充该下拉列表。这是它的关键部分 (1.3.0 version):

    function createItems(field: JQuery < HTMLElement > , opts: AutocompleteOptions) {
      const lookup = field.val() as string;
    
      // ...
      
      let count = 0;
      const keys = Object.keys(opts.source);
      for (let i = 0; i < keys.length; i++) {
        const key = keys[i];
        const object = opts.source[key];
        const item = {
          label: opts.label ? object[opts.label] : key,
          value: opts.value ? object[opts.value] : object,
        };
        if (item.label.toLowerCase().indexOf(lookup.toLowerCase()) >= 0) {
          items.append(createItem(lookup, item, opts));
          if (opts.maximumItems > 0 && ++count >= opts.maximumItems) {
            break;
          }
        }
      }
    
      // skipped the rest
    }
    

    如您所见,每次调用createItems 时,都会经过source 对象,对所有包含查找字符串的项目进行grepping。

    因此,所有数据部分都应该存在 - 并且可以同步处理。这就是插件的方式,这种方式有好有坏。

    插件的作者在这里建议的最好的事情(不违背插件的内容)是在调用自动​​完成之前使用 AJAX 预填充数据。实际上,他在那条评论中就是这样做的。


    现在,这里可以做什么?有人可能认为只需将createItems 转换为异步函数就足够了——例如,如果source 是一个函数并期望其结果是一个Promise,则调用它。排除进程中的查找循环似乎非常简单 - 只需获取 AJAX 调用的结果即可重新填充 source...

    不幸的是,这并不是那么简单:有几个注意事项需要注意。应该发生什么,例如,如果用户停止输入(触发第一个 AJAX 调用),然后再输入一些,然后再次停止(触发另一个 AJAX 调用) - 但第一个实际上稍后到达?相应的错误困扰着我一直在使用的许多自动完成实现,可悲的是 - 如果您仅使用快速网络连接进行测试(更不用说仅在 localhost 上),重现起来并不容易。

    这似乎只是作者决定不扩展该插件的原因之一。毕竟,它是为解决一项特定任务而构建的——而且它做得很好。因此,除非您想将其分叉并从本质上将其重写为“两种策略”之一,否则我建议您考虑寻找其他地方。

    【讨论】:

    • 谢谢raina77ow,一直在下一个兔子洞,并怀疑可能没有另一个开口。很高兴我现在知道了!
    • 再次您好,一直在查看您发布的代码并认为“Javascript 何时支持接口????”搜索并找不到任何东西。然后不幸地发现我被愚弄了。 typescriptlang.org再次感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 2018-09-07
    • 2015-08-13
    • 2014-08-31
    • 1970-01-01
    • 2023-03-05
    • 2016-11-11
    • 2017-12-18
    • 2021-10-20
    相关资源
    最近更新 更多