2013-08-31 137 views
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

是的,你的函數可以與跟蹤哪些回調已定,而當兩者都設置它可以給他們打電話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/

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()已執行。

我創建了an example at JSBin,如果您有興趣看到此代碼在行動。

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(); 
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的工作適合你,那麼你可以有後功能列表。

+0

謝謝。我已經在使用它了。但我試圖擴展它,這樣我也可以獲得「之前」功能。因爲AFAIK,沒有。 – Johan

+0

是的,在功能之前添加是很棘手的。延遲的美妙之處在於,即使延遲解決後,您仍然可以傳遞它們並添加回調,並添加回調函數,這些回調函數在解析後解析之前應該運行,這很棘手......您的用例是什麼樣的? – Douglas

+0

我只是玩了一下,但http://jsfiddle.net/zfqJ8/53/而不是公開承諾,我的想法是公開承諾的一部分+一些自定義方法,例如「之前」。 – Johan

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(); 

做你所期望的。