简体   繁体   English

JavaScript方法链接挑战

[英]JavaScript method chaining challenge

(This question is not really restricted to the language so please feel free to submit solution in other languages too.) (这个问题并不仅限于语言,所以请随意提交其他语言的解决方案。)

I was just wondering if it would be possible to write something like this in JavaScript: 我只是想知道是否可以在JavaScript中编写类似的内容:

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

Where the traditional way would be to write 传统的方式是写作

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

Sorry if this is a noob question :p 对不起,如果这是一个菜鸟问题:p

You can write it easily: 你可以轻松地写它:

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

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

If you want to go in-deep, I recommend you to read about currying and partial function application , those topics are really interesting. 如果您想深入了解,我建议您阅读有关currying部分功能应用的内容 ,这些主题非常有趣。

Yet another version, without closure: 还有另一个版本,没有关闭:

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

With some more code, you can even call the functions repeatedly: 使用更多代码,您甚至可以重复调用函数:

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

Chaining is rather used to execute multiple methods on one object. 链接用于在一个对象上执行多个方法。 So you would rather consider the function as the object and set the timeout there: 所以你宁愿把函数当作对象来考虑并在那里设置超时:

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

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

If you do OO Javascript, then yes, you can do method chaining. 如果你做OO Javascript,那么是的,你可以进行方法链接。

Some of the popular JavaScript frameworks do this. 一些流行的JavaScript框架可以做到这一点。 jQuery does this by returning the jQuery object for functions that usually wouldn't return a value. jQuery通过返回通常不返回值的函数的jQuery对象来完成此操作。

I just wrote a little helper to create APIs like this in a somewhat consistent way, maybe you like it. 我只是写了一个小帮手 ,以一种有点一致的方式创建这样的API,也许你喜欢它。

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

The idea is that you construct a fluent builder with some initial state of type S by calling an entry function. 我们的想法是通过调用入口函数来构造一个具有S类型初始状态的流畅构建器。 Then each chained call transitions the state to a new state. 然后每个链接的调用将状态转换为新状态。

The value you get from chaining a bunch of calls can be executed as a function, which calls exit to construct a value from that state and any options you pass in. 链接一堆调用所得到的值可以作为一个函数执行,它调用exit来从该状态构造一个值以及传入的任何选项。

  • entry : * ⟶ S 进入:*⟶S
  • transition : (S ⟶ *) ⟶ S 过渡:(S⟶*)⟶S
  • exit : S ⟶ (* ⟶ *) 退出:S⟶(*⟶*)

For example 例如

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 */}
});

So 0 , 1 are entry, exit functions. 所以01是入境,出境的功能。 All other functions transition an internal state. 所有其他功能都转换为内部状态。 All functions can take arguments, eg. 所有函数都可以使用参数,例如。 opt

We create an instance of our newly crafted API, 我们创建了一个新制作的API的实例,

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

And call it 并称之为

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

Have a look at the (small) source to see how this is implemented. 看看(小) 来源 ,看看它是如何实现的。

ps. PS。 Used this answer to update docs :D 使用此答案更新文档:D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM