Пристегнитесь, миллениалы, пришло время авантюрной истории лихого Javascript из девяностых — во имя великой справедливости!
Давайте посмотрим на механическое чудо промисов и посмотрим, как на самом деле легко (и, несомненно, удовлетворительно) вручную написать интерфейс с подобным синтаксическим сахаром, не используя Promise()
.
Допустим, мы хотим создать генератор случайных чисел.
И мы также хотели бы знать, нечетное оно или четное. Вот синтаксис, который нам обещали (каламбур):
getRandomNumber(1, 10) .thatsOdd(function(number) { alert(number + ' is odd!') }) .thatsEven(function(number) { alert(number + ' is even!') })
Сладкий. Теперь, как можно создать эту функцию getRandomNumber
?
Чтобы его скомпилировать, нам нужно начать с этой структуры:
function getRandomNumber(min, max) { // return the object that exposes our two methods return { thatsOdd: function(h) { // let each method return this, to allow chaining return this; }, thatsEven: function(h) { // let each method return this, to allow chaining return this; } }; }
Возвращаемая область действия предлагает API нашего обещания. Он содержит два метода thatsOdd
и thatsEven
. Оба метода получают обработчик пользователя, который обрабатывает эту конкретную ситуацию.
Чтобы это работало, нам нужно асинхронно вызвать пользовательский обработчик h
, который они передали в thatsOdd
или thatsEven
. Вот как:
function getRandomNumber(min, max) { // generate the number and see if it's even var number = Math.floor(Math.random() * max) + min; var isEven = number % 2 == 0; // define the final handler var finalHandler; // async call to allow caller to map either handler setTimeout(function() { finalHandler(number); }, 0) // return the object that exposes our two methods return { thatsOdd: function(h) { // map the odd handler that will be called async if (!isEven) finalHandler = h; // let each method return this, to allow chaining return this; }, thatsEven: function(h) { // map the even handler that will be called async if (isEven) finalHandler = h; // let each method return this, to allow chaining return this; } }; }
Вот и все! Вот jsfiddle.
Конечно, есть много оптимизаций, которые можно сделать, но это суть, которая, надеюсь, объясняет немного о том, как создать API с асинхронной цепочкой вручную без беспорядка.
Теперь проведите потрясающий день за своим компьютером.