如何在不使用 'async: false' 且不使用回调的情况下等待 ajax 调用完成?

How can I wait for an ajax call to complete without using 'async: false' and without using callbacks?

我有以下 TypeScript 为我视图中的可点击元素定义了 KnockoutJS 绑定处理程序:

module MyModule {
    export interface ICopyButtonParams {
        dataUrl: string;
    }

    ko.bindingHandlers.copyButton = {
        init: (element: HTMLElement, valueAccessor: () => ICopyButtonParams) => {
            var options: any = ko.utils.unwrapObservable(valueAccessor());
            if (!options.dataUrl) {
                return;
            }

            new Clipboard(element, {
                text: () => {
                    var clipboardData: string;

                    $.ajax({
                        url: options.dataUrl,
                        type: "GET",
                        contentType: "application/json",
                        cache: false,
                        async: false,
                        success: (result: SubmitResult) => {
                            clipboardData = result.Data;
                        }
                    });

                    return clipboardData;
                }
            });
        }
    };
}

此绑定处理程序的作用是将可点击元素转换为 Clipboard.JS 启用元素,该元素在单击时将字符串存储在剪贴板中。在我的例子中,我想利用 Clipboard.JS 的动态文本功能,您可以将一个函数传递给剪贴板构造函数,该函数 returns 您想要存储在剪贴板中的文本。在这个函数中,我想调用 API 来 returns 要存储的文本。

由于这种架构的性质,我无法使用带有成功回调的标准 ajax 调用,因为这意味着无法及时解析剪贴板文本。

作为权宜之计,您会在我的代码中注意到我已将 ajax 调用设为异步(我知道这很糟糕)。由于 'async' 标志从 JQuery 1.8 开始被弃用,我正在尝试考虑一种替代方法。

有什么想法吗?

我认为更好的方法是自己处理点击事件。

然后在您的 ajax 回调中创建一个文本区域,设置值,select 并像 Clipboard.JS 那样调用 document.execCommand('copy')。与此类似的内容(抱歉 javascript 而不是打字稿)

ko.bindingHandlers.copyButton = {
  init: function(element, valueAccessor) {
    var url = ko.utils.unwrapObservable(valueAccessor());

    $(element).click(function() {
      $.ajax({
        url: url,
        type: "GET",
        contentType: "application/json",
        cache: false,
        async: false,
        success: function(result) {
          var ta = document.createElement('textarea');
          document.body.appendChild(ta);
          ta.value = result;
          ta.select();
          var r = document.createRange();
          r.selectNode(ta);
          document.getSelection().addRange(r);
          document.execCommand('copy');
          document.body.removeChild(ta);
        }
      });
    });
  }
};

我有一个类似的工作示例here(没有ajax请求)