2009-09-18 31 views
7

(Câu hỏi này không thực sự bị hạn chế đối với ngôn ngữ, do đó, vui lòng gửi giải pháp bằng các ngôn ngữ khác.)Thử thách phương pháp JavaScript chaining

Tôi đã tự hỏi liệu có thể viết một cái gì đó như thế này trong JavaScript hay không :

// Wait 3 seconds and then say our message in an alert box 
wait(3).then(function(){alert("Hello World!");}); 

đâu theo cách truyền thống sẽ được để viết

// Wait 3 seconds and then say our message in an alert box 
setTimeout(function(){alert("Hello World!");}, 3000); 

xin lỗi nếu điều này là một câu hỏi noob: p

012.
+0

Tôi nghĩ bạn đã trả lời câu hỏi của riêng mình .... điều gì sai với khối mã thứ hai? – Zoidberg

+0

@Zoidberg: Tiêu đề là phương pháp chuỗi để điều ở đây không thực sự là làm cho nó hoạt động nhưng làm cho nó hoạt động bằng cách sử dụng phương pháp chuỗi. – kizzx2

Trả lời

37

Bạn có thể viết nó một cách dễ dàng:

function wait(delay) { 
    return { 
    then: function (callback) { 
     setTimeout(callback, delay*1000); 
    } 
    }; 
} 

wait(3).then(function(){alert("Hello World!");}); 

Nếu bạn muốn đi vào sâu, tôi khuyên bạn nên đọc về curryingpartial function application, những chủ đề đang thực sự thú vị.

+0

Đánh tôi quá! – Zoidberg

+0

Huy hiệu typer nhanh. (hoặc đã sẵn sàng chưa?) –

+0

@cemkalyoncu: Tôi là người đánh máy nhanh và tôi sử dụng ấn bản giống như Vim ở mọi nơi: -D – CMS

0

Nếu bạn làm OO Javascript, thì có, bạn có thể làm phương pháp chuỗi.

Một số khung JavaScript phổ biến làm điều này. jQuery thực hiện điều này bằng cách trả về đối tượng jQuery cho các hàm thường không trả về một giá trị.

2

Chuỗi được sử dụng để thực thi nhiều phương pháp trên một đối tượng. Vì vậy, bạn thà xem xét các chức năng như đối tượng và thiết lập thời gian chờ có:

Function.prototype.callAfter = function(delay) { 
    setTimeout(this, delay*1000); 
}; 

(function(){alert("Hello World!");}).callAfter(3); 
14

Tuy nhiên, phiên bản khác, mà không đóng cửa:

function wait(seconds) { 
    if(this instanceof wait) 
     this.delay = seconds; 
    else return new wait(seconds); 
} 

wait.prototype.then = function(callback) { 
    setTimeout(callback, this.delay * 1000); 
}; 

Với một số mã hơn, bạn thậm chí có thể gọi các chức năng liên tục:

function wait(seconds) { 
    if(this instanceof wait) 
     this.delay = seconds; 
    else return new wait(seconds); 
} 

wait.prototype.then = function(callback) { 
    setTimeout(callback, this.delay * 1000); 
    return this; 
}; 

wait.prototype.wait = function(seconds) { 
    this.delay += seconds; 
    return this; 
}; 

var start = new Date; 
function alertTimeDiff() { 
    alert((new Date - start)/1000); 
} 

wait(1).then(alertTimeDiff).wait(3).then(alertTimeDiff); 
+0

@Christoph: Cách tiếp cận của bạn tốt và là những gì tôi nghĩ là toàn diện hơn CMS '. Nhưng sau đó một lần nữa ông trả lời câu hỏi một cách chính xác nhanh hơn vì vậy tôi đã đưa ra câu trả lời đúng cho anh ta: p – kizzx2

0

Tôi vừa viết little helper để tạo API như thế này theo cách hơi nhất quán, có thể bạn thích nó.

// > npm i mu-ffsm # install node dependency 
var mkChained = require('mu-ffsm'); 

Ý tưởng là bạn xây dựng trình tạo thông thạo với một số trạng thái ban đầu S bằng cách gọi hàm nhập. Sau đó, mỗi chuỗi cuộc gọi chuyển trạng thái sang trạng thái mới. .

Giá trị bạn nhận được từ chaining được kết một loạt các cuộc gọi có thể được thực hiện như một chức năng, trong đó kêu gọi exit để xây dựng một giá trị từ trạng thái đó và bất kỳ tùy chọn bạn vượt qua trong

  • nhập: * ⟶ S
  • chuyển: (S ⟶ *) ⟶ S
  • exit: S ⟶ (* ⟶ *)

Ví dụ

var API = mkChained({ 
    0: function(opt) {return ;/* create initial state */}, 
    then: function(s, opt) {return s; /* new state */}, 
    whut: function(s, opt) {return s; /* new state */}, 
    1: function(s, opt) {return ;/* compute final value */} 
}); 

Vì vậy, 0, 1 là các chức năng nhập cảnh, thoát. Tất cả các chức năng khác chuyển đổi trạng thái bên trong. Tất cả các chức năng có thể lấy đối số, ví dụ:opt

Chúng tôi tạo ra một thể hiện của API mới được chế tác của chúng tôi,

var call = API() // entry 
    .whut()  // transition 
    .then()  // transition 
    .whut();  // transition 

Và gọi nó là

var result0 = call() // exit 
    , result1 = call() // exit 

Có một cái nhìn tại (nhỏ) source để xem cách này được thực hiện.

ps. Sử dụng câu trả lời này để cập nhật tài liệu: D

+0

Tại sao bỏ phiếu xuống? – wires

Các vấn đề liên quan