解決ajax多次綁定問題

來源:互聯網
上載者:User

標籤:例子   submit   抓取   track   highlight   任務   連續   服務   大神   

博主最近在項目中遇到一個挺頭大的問題,點擊按鈕觸發一次ajax,但是實際中會發現ajax提交次數會隨著點擊次數遞增,十分頭疼,

找了度娘之後發現ajax請求一次就綁定一次,解決辦法是可以再出發下一次之前先將事件解除綁定,再添加上事件便不會多次出發。

總結起來就是:一般綁定事件後,觸發多次的原因是,在其他地方也綁定過。如果實在找不到在哪裡綁定過可以這樣:在綁定事件之前,

先用unbind()方法或者off()方法解除綁定後,再重新綁定一下。再就是不排出是否是其他標籤事件冒泡到這個標籤上來了的可能性。

博主覺得很有意思便多研究了下,現在將組織多次出發的方法也附在下面:

A. 獨佔提交只允許同時存在一次提交操作,並且直到本次提交完成才能進行下一次提交

module.submit = function() {
  if (this.promise_.state() === ‘pending‘) {    return  }  return this.promise_ = $.post(‘/api/save‘)}
B. 貪婪提交
無限制的提交,但是以最後一次操作為準;亦即需要儘快給出最後一次操作的反饋,而前面的操作結果並不重要。
module.submit = function() {  if (this.promise_.state() === ‘pending‘) {    this.promise_.abort()  }  // todo}
比如某些應用的條目中,有一些進行類似「喜歡」或「不喜歡」操作的二態按鈕。如果按下後不立即給出反饋,使用者的目光焦點就可能在那個按鈕上停頓許久;如果按下時即時轉換按鈕的狀態,再在程式上用 abort 來實現積極的提交,這樣既能提高使用者體驗,還能降低伺服器壓力,皆大歡喜。
C. 節制型提交
無論提交如何頻繁,任意兩次有效提交的間隔時間必定會大於或等於某一時間間隔;即以一定頻率提交。
module.submit = throttle(150, function() {  // todo})
如果客戶發送每隔100毫秒發送過來10次請求,此模組將只接收其中6個(每個在時間軸上距離為150毫秒)進行處理。
這也是解決查詢衝突的一種可選手段,比如以知乎草稿舉例,仔細觀察可以發現:
編輯器的 blur 事件會立即觸發儲存;
儲存按鈕的 click 事件也會立即觸發儲存;
但是存在一種情況會使這兩個事件在數毫秒內連續發生——當焦點在編輯器內部,並且直接去點擊儲存按鈕——這時用 throttle 來處理是可行的。
另外還有一些事件處理會很頻繁地使用 throttle,如: resize、scroll、mousemove。
D. 懶惰提交
任意兩次提交的間隔時間,必須大於一個指定時間,才會促成有效提交;即不給休息不幹活。
module.submit = debounce(150, function() {  // todo})
方式 C 和 方式 D 有時更加通用,比如這些情況:
  • 遊戲中你撿到一把威力強大的高速武器,為了防止你的子彈在螢幕上打成一條直線,可以 throttle 來控制頻率;
  • 在彈幕型遊戲裡,為了防止你把射擊鍵夾住來進行無腦遊戲,可以用 debounce 來控制頻率;
  • 在編譯任務裡,守護進程監視了某一檔案夾裡所有的檔案(如任一檔案的改變都可以觸發重新編譯,一次執行就需要2秒),但某種操作能夠瞬間造成大量檔案改變(如 git checkout),這時一個簡單的 debounce 可以使編譯任務只執行一次。
而方式 C 甚至可以和方式 B 組合使用,比如自動完成組件(Google 首頁的搜尋就是):
  • 當使用者快速輸入文本時(特別是打字能手),可以 throttle keypress 事件處理函數,以指定時間間隔來提取文本域的值,然後立即進行新的查詢;
  • 當新的查詢需要發送,但上一個查詢還沒返回結果時,可以 abort 未完成的查詢,並立即發送新查詢;
E. 記憶型
var scrape = memoize(function(url) {  return $.post(‘/scraper‘, { ‘url‘: url })})
對於同樣的參數,其返回始終結果是恒等的——每次都將返回同一對象。
應用例子有編輯器,如粘貼內容時抓取其中的連結資訊,memoize 用以保證同樣的連結不會抓取兩次。

F. 累積型
前幾天處理自動完成事件時得到這個函數,發現也可以用在處理連續事件上,它能夠把連續的多次提交合并為一個提交,比如:
var request = makePile(5, function() {    $.post(‘/‘, { list: JSON.stringify([].slice.call(arguments)) })})// 連續發送五次 request({a:1}), request({a:2}), request({a:3}), request({a:4}), request({a:5})/* post =>list:[{"a":1},{"a":2},{"a":3},{"a":4},{"a":5}] */
範例實現:
var makePile = function(count, onfilter, onvalue) {  var values = [], id = function(value) { return value }  return function(value) {    values.push((onvalue || id).apply(this, arguments))    if (values.length === count) {      onfilter.apply(this, values)      values = []    }  }}

另一種累積是按時間而不是次數,比如應用在行為統計上,可能在瞬間收集到數十上百類似的行為,這時可以用上面 pile 的結構加上 debounce 來防止大批重複請求(但又不丟失任何統計):
var trackFactory = function(delay, action) {  var params = [], slice = [].slice  var touch = debounce(delay, function() {    if (params.length) {      action(params)      params = []    }  })  return function() {    params.push(slice.call(arguments))    touch()  }}var track = trackFactory(550, function(params) {  // send tracking request})
G. 採樣型
這是最近重構時聯想到的,一種和上面都不同的去重操作,可以應用在自動載入(timeline)行為控制上:
autoload.listen(feeds, ‘next‘, sample(3, function() {  this.enable()}))
如果 sample 是固化的選擇函數(n 選 1),它這實際上會這樣工作:
O-O-X-O-O-X
但「自動載入」的應用可能想要的是(兩次自動,一次手動):
X-X-O-X-X-O
對於這種情況,可以定義作為配置的選擇函數來實現控制:
options { sample: (n) => n % 3 !== 0 }
即每個下一次載入完成之後, 每三次有兩次對下一次載入實行自動載入。感謝知乎大神 長天之雲

解決ajax多次綁定問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.