Передача аргументов при асинхронном запуске потока lodash

#javascript #functional-programming #lodash #currying #function-composition

#javascript #функциональное программирование #lodash #каррирование #функция-композиция

Вопрос:

Учитывая приведенный ниже код, как я могу передать идентификатор функции applySaveAsync?

    var then = _.curry(function (f, thenable) {
        return thenable.then(f);
    });

    var validateAsync = _.flow(
        function () { return _(someCondition).showError(ERROR_01).value(); },  
        then(function () { return _(anotherCondition).showError(ERROR_02).value(); }) 
    );

    var save = _.flow(
        validateAsync,
        then(applySaveAsync),
        then(saveCompleted)
    );

    function applySaveAsync(id) {
        // Saving...
    }

    save(22); // Calling save function with some id.
  

Я могу получить идентификатор функции validateAsync, но я не могу вернуть его обратно, поскольку validateAsync должен возвращать обещание.

Любой способ добиться этого?

Комментарии:

1. Я не думаю, что lodash curry amp; flow знают об обещаниях. И я не уверен, что они добавляют в таблицу, даже если бы они были. Если бы у вас было сохранение как обычная функция, идентификатор был бы записан (работа выполнена).

2. Что значит «вы не можете вернуть его обратно»? Насколько я вижу, ваша validateAsync функция возвращает обещание, которое выполняется с идентификатором. В чем ваша проблема? Может быть, покажите нам больше вашего кода.

3. @Bergi я включил код validateAsync . Спасибо за вашу помощь

4. @Keith Меня больше интересует написание этого кода с использованием функционального программирования, я знаю, что его можно легко решить, используя обычную функцию или даже выставляя id в качестве глобальной переменной.

Ответ №1:

Самым простым выбором было бы не использовать _.flow для определения validateAsync .
Поскольку validateAsync не принимает параметры и не имеет результата, вам следует просто изменить определение save , чтобы не использовать _.flow :

 function save(id) {
    return validateAsync()
    .then(function(){ return applySaveAsync(id) })
    .then(saveCompleted)
}
  

Мы также могли бы изменить validateAsync , чтобы передать через id :

 function validateAsync(id) {
    return _(someCondition).showError(ERROR_01).value()  
    .then(function () { return _(anotherCondition).showError(ERROR_02).value(); })
    .then(_.constant(id));
}
  

и даже делайте это, все еще используя _.flow

 var validateAsync = _.flow(
    function(id) { return _(someCondition).showError(ERROR_01).value().then(_.constant(id)); },  
    then(function(id) { return _(anotherCondition).showError(ERROR_02).value().then(_.constant(id)); }) 
);
  

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

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

 function pass(fn) {
    return function(id) {
        return fn().then(function() {
            return id;
        });
    }
}
  

(если вы предпочитаете, вы можете попытаться составить это из then _.constant и многое другое)
чтобы можно было написать

 var save = _.flow(
    wrap(validateAsync),
    then(applySaveAsync),
    then(saveCompleted)
);
  

Комментарии:

1. Вы думаете, что нет способа передать id композицию using? (Я все еще изучаю fp).

2. @Anas смотрите редактирование. Если вы хотите использовать композицию, вам нужен какой-то способ передачи id через или вокруг validateAsync . Большая проблема validateAsync заключается в том, что он не является чистым (вызывается только для побочных эффектов) и не принимает аргумент, что делает его очень плохим

3. Большое спасибо за ваше объяснение.

4. Это хорошо. Я создал свою функцию ‘then’ следующим образом «const then = <T>(fn) => { return (input: Promise<T>) => input.then(fn); }; «

Ответ №2:

Я нашел этот пакет полезным для вас. В асинхронных случаях вы можете использовать этот пакет.

Хотя flow является одной из лучших реализаций для декларативного программирования, он не поддерживает современный стиль программирования на JS.

 import { Conductor } from '@puzzleio/conductor';

const conductor = Conductor.createDefault();

const myAsyncWorkflow = conductor
  .add(validateAsync)
  .if({
    check: item => item.isValid === true,
    handler: item => console.log('Item is valid')
  },
  {
    // else block
    handler: item => console.log('Validation failed')
  });

myAsyncWorkflow.run(obj)
  .then(() => console.log('Successfully validated'))
  .catch(console.error);