在异步运行lodash流时传递参数

时间:2016-10-01 05:34:45

标签: javascript functional-programming lodash currying function-composition

根据以下代码,如何将 id 传递给 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 函数中获得 id ,但我无法将其返回,因为 validateAsync 应该返回一个承诺。

有任何方法可以实现这一目标吗?

2 个答案:

答案 0 :(得分: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 :(得分:0)

我发现这个包对你很有用。在异步情况下,您可以使用 this package

虽然流是声明式编程的最佳实现之一,但它不支持现代 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);