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

在不使用'async:false'和不使用回调的情况下,如何等待ajax调用完成?,ajax,asynchronous,knockout.js,typescript,clipboard.js,Ajax,Asynchronous,Knockout.js,Typescript,Clipboard.js,我有以下类型脚本,为视图中的可单击元素定义KnockoutJS绑定处理程序: module MyModule { export interface ICopyButtonParams { dataUrl: string; } ko.bindingHandlers.copyButton = { init: (element: HTMLElement, valueAccessor: () => ICopyButtonParams) =&

我有以下类型脚本,为视图中的可单击元素定义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的动态文本功能,通过该功能,您可以将一个函数传递到剪贴板构造函数中,该构造函数返回要存储在剪贴板中的文本。在这个函数中,我想调用一个API,返回要存储的文本

由于这种体系结构的性质,我无法将标准ajax调用与成功回调一起使用,因为这意味着剪贴板文本将无法及时解析

作为一种权宜之计,您会在我的代码中注意到,我知道我的ajax调用异步性很差。由于jQuery1.8以后就不推荐使用“async”标志,因此我正在尝试另一种方法


有什么想法吗?

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

然后在ajax回调中创建一个textarea,设置值,选择并调用document.execCommand“copy”,就像Clipboard.JS那样。类似于此的东西,请在typescript上使用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);
        }
      });
    });
  }
};

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

为什么不先调用异步ajax,然后在成功回调中创建Cliboard对象呢?关键是我不想检索要放在剪贴板中的数据,除非需要,例如有人单击“复制到剪贴板”按钮。页面上可能有100多个东西可以复制到剪贴板,每个都包含许多文本字符。如果我要用剪贴板按钮应该存储的数据对每个剪贴板按钮进行预初始化,我还可以用视图模型的其余部分检索剪贴板文本,并完全取消ajax调用。值得指出的是,复制到剪贴板上的内容从来都不是页面上显示的内容。也许我不理解您的意思,但您应该只在希望以这种方式运行的元素上放置data bind=copyButton:{},或者?正确,但我只希望这些元素在单击时加载相应的剪贴板文本。在这种情况下,我可能只创建一个函数,例如在按钮上单击绑定时调用该函数。点击我是的,最后我自己也采用了这种方法。JS的设计过于规范。很好,它包装了所有黑客的东西,比如创建文本区域,但不值得这么麻烦。谢谢你的回复!这种方法在Firefox中不再有效,导致错误:document.execCommand'cut'/'copy'被拒绝,因为它不是从短时间运行的用户生成的事件处理程序中调用的。据英国《每日邮报》报道,拥有剪贴簿写入权限可以解决这个问题