2016-05-17 75 views
1

我有以下打字稿定义在我看来一个可点击的元素的KnockoutJS绑定处理程序:如何等待ajax调用完成而不使用'async:false'而不使用回调?

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的动态文本功能,将一个函数传递到剪贴板构造函数中,该函数返回要存储在剪贴板中的文本。在这个函数内部,我想调用一个返回要存储的文本的API。

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

作为一种临时补救措施,您会在我的代码中注意到我使ajax调用异步(不好,我知道)。由于从JQuery 1.8开始不赞成使用“异步”标志,因此我试图想出另一种方法。

任何想法?

+1

你为什么不先调用一个异步AJAX,然后在成功回调你可以创建Cliboard对象吗? – mirage

+0

整个问题是我不想检索要放入剪贴板的数据,除非需要(即有人点击“复制到剪贴板”按钮)。页面上可能有100多个可复制到剪贴板的东西,每个东西都包含许多文本字符。如果我要预先初始化每个剪贴板按钮以及它应该存储的数据,那么我可能会用视图模型的其余部分检索剪贴板文本,并完全抛弃ajax调用。值得指出的是,正在复制到剪贴板的东西永远不会显示在页面上。 – aleonj

+0

也许我不明白你是对的,但是你只应该把data-bind =“copyButton:{}”放在你想要这样做的元素上,或者? – mirage

回答

1

我认为更好的approuch将是由您自己处理点击事件。

然后在你的ajax回调函数中创建一个textarea,设置值,选择并调用document.execCommand('copy')作为Clipboard.JS。同样的事情也该(对不起,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请求)

+0

是的,我最终自己到了这个方法。 Clipboard.JS的设计过于规范。它很好,它包装了所有“hacky”的东西,比如创建textareas,但它不值得冒险。感谢您的回复! – aleonj