2

我想获得与此类似的功能:

function foo(before, after){

    before();

    setTimeout(function(){
         after();
    },100)
}

foo(function(){
    console.log('before');
}, function(){
    console.log('after');
});

当返回一个对象而不是使用回调(伪代码)时:

var foo = function() {

     before();         

     setTimeout(function(){
         after();
     },100)

     return {
         before: before,
         after: after
     }
};

foo().before(function(){
    console.log('before');
});

foo().after(function(){
    console.log('after');
});

或者甚至可能

foo().before(function(){
    console.log('before');
}).after(function(){
    console.log('after');
});

这可能吗?

4

5 回答 5

4

是的,您的函数可以返回一个对象beforeafter方法来跟踪已设置的回调,并且当两者都设置时,它可以调用它们:

function foo() {

    var beforeFunc = null, afterFunc = null;

    function activate() {
        beforeFunc();
        window.setTimeout(afterFunc, 100);
    }

    var obj = {
        before: function(f) {
            beforeFunc = f;
            if (afterFunc != null) activate();
            return obj;
        },
        after: function(f) {
            afterFunc = f;
            if (beforeFunc != null) activate();
            return obj;
        }
    };

    return obj;

}

// As both callbacks need to be set, the order is not important
foo().after(function(){
    console.log('After');
}).before(function(){
    console.log('Before');
});

演示:http: //jsfiddle.net/4HypB/

于 2013-08-31T23:18:55.680 回答
2

几乎是可能的。

但是,您提出的使用示例的问题在于它涉及在指定foo()之前调用beforeafter回调。同时,在您的示例实现中,这些回调在foo. 所以是无法实现的:在该方法已经运行之后,您不能追溯更改该方法中发生的事情。

如果您真正想要的是通过提供的回调几乎foo立即执行——即,如果纯同步执行不是强制性的——你可以通过一个简单的调用得到你想要的:setTimeout

function foo() {
  var callbacks = {
    before: function() {},
    after: function() {}
  };

  setTimeout(function() {
    callbacks.before();
    setTimeout(callbacks.after, 100);
  }, 0);

  return {
    before: function(callback) {
      callbacks.before = callback;
      return this;
    },

    after: function(callback) {
      callbacks.after = callback;
    }
  };
}

在这里,foo()将返回一个对象,该对象公开方法以修改callbacks在方法体内封闭的对象foo。这些方法将在事件循环的下一个滴答中使用, foo()执行之后。

如果您有兴趣查看此代码的实际效果,我在 JSBin 创建了一个示例。

于 2013-08-31T23:15:29.043 回答
1
function foo(){};
foo.prototype.before = function(f){ this._before = f };
foo.prototype.after  = function(f){ this._after  = f };
foo.prototype.go = function(){
  this._before();
  setTimeout(this._after,100);
}

var f = new foo;
f.before(function(){ … });
f.after(function(){ … });
f.go();

但话又说回来,你不妨让这更简单:

function foo(){};
foo.prototype.go = function(){
  this.before();
  setTimeout(this.after,100);
}

var f = new foo;
f.before = function(){ … };
f.after  = function(){ … };
f.go();
于 2013-08-31T23:15:50.193 回答
1

这是另一个变体:

var createFooBuilder = function () {
    var before = function() {};
    var after = function() {};

    var func = function () {
        before();
        setTimeout(function () {
            after();
        }, 100)
    };

    func.before = function(value) {
        before = value;
        return func;
    }
    func.after = function(value) {
        after = value;
        return func;
    }

    return func;
};

var foo = createFooBuilder();

foo.before(function () {
    console.log('before');
}).after(function () {
    console.log('after');
});

foo();

我当然建议您尝试让jQuery Deferred为您工作,然后您可以拥有 after 函数的列表。

于 2013-08-31T23:18:24.677 回答
1

Phrogz 的回答很好,但 FWIW 你也可以在没有原型的情况下做到这一点:

function foo() {
  ret = function () { return ret.call(); };
  ret.call = function () {
    this._before();
    setTimeout(this._after,100);
  };
  ret.before = function (x) { this._before = x; return this; };
  ret.after = function (x) { this._after = x; return this; };
  return ret;
};

test = foo().before(function(){
  console.log('before');
}).after(function(){
  console.log('after');
});

来电:

test();

做你所期望的。

于 2013-08-31T23:20:29.973 回答