2016-05-17 79 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