如何在发送keyup事件时避免出现比赛情况

How to avoid a race condition when keyup event is sent

本文关键字:情况 事件 keyup      更新时间:2023-09-26

我有一个函数matcher,每次发送keyup事件时都会调用它。

这个函数属于一个模块,它看起来像(1)
如果在获取完成之前进行了另一个调用,该怎么办
如何在本模块(1)中解决此问题?


(1)

(function ($, UserCollection) {
    var userCollection;
    var matcher = function (request, response) {
        if (!userCollection) {
            userCollection = new UserCollection();
            userCollection.fetch();
        } else {
            isMatched(request, response);
        }
    };
    return matcher;
}(jquery, UserCollection));

我将采用一种不同的方法,可能过于夸张,并使用collection.fetch返回的jqXHR对象。

var Matcher=(function($,UserCollection) {
    var xhr=null, userCollection=null;
    // matching against a defined ID for testing purpose
    function isMatched(id) {
        return userCollection.get(id);
    }
    // the request would be an ID in my example,
    // and the callback is the function invoked when the collection is fetched
    function matcher(request, callback) {
        if (!xhr) {
            userCollection = new UserCollection();
            // fetch returns a handy xhr object used for the deferred
            xhr=userCollection.fetch(); 
        }
        xhr.then(function() {
            callback(isMatched(request));
        });
    }       
    return matcher;
})(jQuery, UserCollection);

如果xhr已经解析,则会立即调用回调,如果没有,则会在请求完成时调用:有关更多信息,请参阅jQuery.Deferred。

你会用它作为

Matcher(1,console.log);
Matcher(2,console.log);

和小提琴http://jsfiddle.net/EWSAV/1/

只要运行同步操作,这应该没有问题,因为事件会及时执行。

但是,您可以添加第二个变量,指示是否正在进行匹配。

类似这样的东西:

(function ($, UserCollection) {
    var userCollection;
    var inProgress = false;
    var matcher = function (request, response) {
        if (!inProgress){
           if (!userCollection) {
               inProgress = true;
               userCollection = new UserCollection();
               userCollection.fetch();
           } else {
               isMatched(request, response);
           }
           // inProgress = false; - after your asynchonous code is executed
        }
    };
    return matcher;
}(jquery, UserCollection));

这个代码可能不起作用,但我想你已经明白了。

然而,这种方法可能需要异步脚本在相同的范围内才能访问inProgress。更好的选择可能是在提取时使用回调:

userCollection.fetch({ success:function(){inProgress=false} });

根据Backbone.js文档,fetch()接受在成功"获取"后调用的回调函数。因此,您可以有一个全局变量来指示当前"fetch"的状态。这是基本的想法,我认为你可以从这里开始工作

fetching = false;
//Event fired ->
if (!fetching ){
fetching = true;
..fetch({success: function(){fetching = false;}});
}