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