Задача цепочки методов JavaScript

(этот вопрос на самом деле не ограничивается языком, поэтому, пожалуйста, не стесняйтесь представить решение и на других языках.)

мне просто интересно, можно ли написать что-то подобное в JavaScript:

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

где традиционным способом было бы написать

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

Извините, если это вопрос noob :p

5 ответов


вы можете легко написать:

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

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

Если вы хотите углубиться, я рекомендую вам прочитать о карринг и частичное применение функции, эти темы действительно интересны.


еще одна версия, без закрытия:

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

С некоторым больше кода, Вы можете даже вызвать функции повторно:

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

цепочки, а используется для выполнения нескольких методов на одном предмете. Поэтому вы предпочли бы рассматривать функцию как объект и установить тайм-аут там:

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

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

Если вы делаете Oo Javascript, то да, вы можете сделать цепочку методов.

некоторые из популярных фреймворков JavaScript делают это. jQuery делает это, возвращая объект jQuery для функций, которые обычно не возвращают значение.


Я только что написал маленький помощник чтобы создать API, как это в несколько последовательным образом, может быть, вам это нравится.

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

идея заключается в том, что вы строите fluent builder с некоторым начальным состоянием типа S путем вызова функции ввода. Затем каждый цепной вызов переводит состояние в новое состояние.

значение, которое вы получаете от цепочки вызовов, может быть выполнено как функция, которая вызывает exit для построения значения из этого состояния и любого вариантов вы передаете.

  • вход : * ⟶ Ы
  • переход: (S⟶*)
  • выход : с ⟶ (* ⟶ *)
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 */}
});

так 0, 1 функции входа, выхода. Все остальные функции переходят во внутреннее состояние. Все функции могут принимать аргументы, например. opt

мы создаем экземпляр нашего недавно созданного API,

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

и называть это

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

есть посмотрите на (маленький)источник чтобы увидеть, как это реализуется.

ps. Использовал этот ответ для обновления документов: D