cbdeveloper
cbdeveloper

Reputation: 31365

How to combine 2 Javascript functions into one?

I have the following function, which I want to re-use as an "action" template and pass another function as a parameter, which will be the action function, to be executed in the middle of it.

QUESTION

Is it possible? How can I do it?

Note that the "action" is asynchronous and also I'm using React.

  function templateAction(action) {
    try {
      setLoading(true);
      setError(null);

      // DO SOMETHING
      action();

      setLoading(false);
    }
    catch(err) {
      console.log(err);
      setError(err);
      setLoading(false);
    }
  }

And inside that action() call should execute the following function:

  async function getBlogPost() {
    const querySnapshot = await firebase.firestore().collection('blog').where('slug','==',props.match.params.slug).get();
      console.log(querySnapshot.docs);
      if (querySnapshot.docs.length === 0) {
        throw 'ERROR: BlogPost not found...';
      } else if (querySnapshot.docs.length > 1) {
        throw 'ERROR: More than 1 blogPost found...';
      }

      const blogPostData = querySnapshot.docs[0].data();

      setFirestoreID(querySnapshot.docs[0].id);
      setBlogPost(blogPostData);
  }

SNIPPET

I think that I've built the behavior that I need (run snippet). Can I do it simpler than that? It seems a lot of boilerplate.

async function templateAction(action) {
  try {
    console.log('Template Action BEFORE calling action');
    await action();
    console.log('Template Action AFTER calling action');
  }
  catch(err) {
    console.log(err);
  }
}

function action() {
  return new Promise(async (resolve,reject) => {
    console.log('I am sync from action function BEFORE async call');
    await mockAPI();
    console.log('I am sync from action function AFTER async call');
    resolve();
  });
}

function mockAPI() {
  return new Promise((resolve,reject) => {
    setTimeout(() => {
      console.log('I am from async mockAPI call');
      resolve();
    },1500);
  });
}

templateAction(action);

Upvotes: 0

Views: 101

Answers (2)

cbdeveloper
cbdeveloper

Reputation: 31365

Here is my final code, with error catching using try catch blocks.

It works, though I think it hurts readability.

async function templateAction(action) {
  try {
    console.log('Template Action BEFORE calling action');
    await action();
    console.log('Template Action AFTER calling action');
  }
  catch(err) {
    console.log('I was caught and logged');
    console.log(err);
  }
}

function action() {
  return new Promise(async (resolve,reject) => {
    try {
      console.log('I am sync from action function BEFORE async call');
      await mockAPI();
      console.log('I am sync from action function AFTER async call');
      resolve();
    }
    catch(err) {
      console.log('I was caught');
      reject(err);
    }
  });
}

function mockAPI() {
  return new Promise((resolve,reject) => {
    setTimeout(() => {
      console.log('I am from async mockAPI call');
      resolve();
    },1500);
  });
}

templateAction(action);

Upvotes: 0

Bruno Leyne
Bruno Leyne

Reputation: 369

You can pass by anonymous function like this: https://codesandbox.io/embed/awesome-mayer-52ix7

function templateAction(action) {
  action();
}

let test = function() {
  alert("test");
};

templateAction(test);

For the async part, maybe you will need to make promise, depending if you need a confirmation for the action. With reactJS you can make this more simple by using scope sending properties and getting using "this.props"

Upvotes: 2

Related Questions