Anas
Anas

Reputation: 5727

Passing arguments while running lodash flow asynchronously

Given the code below, how can I pass id to the applySaveAsync function?

   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.

I can get the id on the validateAsync function, but I cannot return it back since validateAsync should return a promise.

Any way to achieve that?

Upvotes: 0

Views: 2319

Answers (2)

Danial Manavi
Danial Manavi

Reputation: 1

I found this package useful for you. In Async cases, you can use this package.

Although flow is one of the best implementations for declarative programming, it doesn't support modern JS programming style.

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

Upvotes: 0

Bergi
Bergi

Reputation: 664548

The simplest choice would be not to use _.flow for the definition of validateAsync.
Since validateAsync does not take parameters nor has a result, you should just change the definition of save to not use _.flow:

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

We could also change validateAsync to pass through the id:

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

and even do that while still using _.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)); }) 
);

but I would advise against that since validateAsync is not supposed to be a function that does takes parameters.

Let's write a wrapper function for such instead to let us do the pass-around in a functional way:

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

(if you prefer, you can try to compose that from then, _.constant and more)
so that one can write

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

Upvotes: 3

Related Questions