如何取消使用angucomplete-alt remote-api-handler进行的请求?

时间:2016-05-17 13:15:35

标签: javascript angularjs

此问题与Angucomplete-alt directive

有关

注意:我使用的是Angular 1.4

我正在使用remote-api-handler参数来填充angucomplete-alt指令的选项。 如果在进行新查询后收到回复或文本字段失去焦点,我希望能够取消由angucomplete-alt 发出的查询。为此,我检查响应的配置属性,并在失去焦点时设置标志。 到目前为止,我已经设法通过向angucomplete-alt发送空数据数组来处理这种情况,但这会产生不良副作用,即显示无结果占位符并显示文本字段后面的下拉列表失去了焦点。

理想情况下,我希望实现以下目标:

  • 如果在结果到达之前完成了新请求,则取消请求 显示text-searching占位符而不是 text-no-results一个。

  • 如果失去焦点则取消请求并阻止angucomplete-alt打开其下拉列表。

我的直觉是我应该使用remote-api-handler第二个参数(timeoutPromise),但到目前为止我还没有成功。有人会知道如何很好地解决这个用例吗?也许你会采取与我正在尝试的策略不同的策略?

以下是定义angucomplete-alt指令的html模板的一部分:

  <angucomplete-alt id="suggestions"
                    placeholder="Search something"
                    pause="100"
                    selected-object="vm.selected"
                    remote-api-handler="vm.apiHandler"
                    title-field="key"
                    minlength="1"
                    maxlength="70"
                    text-searching="search in progress"
                    text-no-results="nothing found"
                    focus-in="vm.focusIn()"
                    focus-out="vm.focusOut()">
  </angucomplete-alt>

这是控制器处理来自angucomplete-alt:

的请求
angular
    .module('my-module')
    .controller('FieldController', FieldController);

  function FieldController(apiService) {
    var self = this;
    var previousSelectedTitle = '';

    self.infocus = false;
    self.currentString = '';

    self.apiHandler = apiHandler;
    self.focusIn = focusIn;
    self.focusOut = focusOut;
    self.selected = selected;

    function apiHandler(string, timeoutPromise) {
      self.currentString = string;
      return apiService.get(string)
      .then(function(result){
        //prevents late responses to display - should use timeoutPromise?
        if(!self.infocus || result.config.params.string !== self.currentString){
          return {data: []};
        }
        else{
          return result;
        }
      }
    }

    function focusIn() {
      self.infocus = true;
    }

    function focusOut() {
      self.infocus = false;
    }

    function selected(selectedObj) {
      if (angular.isUndefined(selectedObj) ||!self.infocus) {
        return;
      }
      //Do something great with the selected object
    }
  }

2 个答案:

答案 0 :(得分:0)

自定义处理程序的第二个参数并不完全是超时承诺,而是取消承诺。仅当搜索已经在进行但用户继续输入并且现在输入已更改时,promise才得以解决。

我一直在使用Promise.race,它似乎可以使插件正常工作:

function apiHandler(string, nevermind) {
  return Promise.race([apiService.get(string), nevermind]);
}

答案 1 :(得分:0)

Tom McClure的答案几乎是正确的,有关Promise.race的正确实现,请参见下面的代码,

在控制器文件中添加以下代码

function apiHandler(string) {
  return Promise.race([apiService.get(string)]);
}

在上面的代码中,promise.race将考虑需要较长时间而忽略其他API的api。

您还可以通过添加超时来取消上一个api调用,这样您将获得最新api调用的响应

var handler = $q.defer()
$http.get('url', {
timeout: handler.promise
})

要取消上一个api调用,只需调用handler.resolve()即可取消api调用

handler.resolve() //which will cancel the previous api call

这可能会对您有所帮助。