Using try ... catch block in a job

Hello there,

Can I use a try … catch block with in a single job
My scenario
I’m using the http adaptor to try and add data to akeneo, which has variables set up as option lists

what I’m looking for is something like


get("www.example.com/1"); // header params
.
.

try {
    // check if variable exists
    fn(state => {
        var x = state.references[0].x.toLowerCase().trim();
        return get(`.../attributes/x/options/${x}`); // returns a 404 if it doesn't exist
    });
} catch (error) {
    post(`.../attributes/x/options`, {
        body: state => {
            return {
                "code": state.references[0].x.toLowerCase().trim(),
                "value": state.references[0].x
            };
        },
        header: state => {
            return {
                "y": state.references[1].y
            };
        },
    }); // create the option
}

Which I run for 8 more variables before finally adding the product with the variables set to their respective options

Problem is, state in the catch clause resets to initial state (empty references and data is one received in inbox)
also, Is this the right approach to creating a job like this?

1 Like

Very cool concept @etdvlpr !
(cc: @Mamadou , @stu in case you have anything to add)

A few suggestions:

  1. At the time of writing, you can’t use try/catch at the top level like that. Everything at the top level needs to be an operation. Also, as a general rule of thumb, your custom Javascript should go inside an fn operation.

  2. Most of the functions that you’d commonly use at the top level will expect to be called with state… so if you use them inside a custom fn block, you’ll need to do so. For example, return get('url'); should become return get('url')(state) if you want to execute it inside an fn block.

  3. The “OpenFn way” of doing this would likely be with promises, making use of .then(), .catch(), and .finally(). Consider the code (with some of your data transformation commented out) below:

get('https://jsonplaceholder.typicode.com/todos/1'); // header params

// check if variable exists
fn(state => {
  // var x = state.references[0].x.toLowerCase().trim();

  console.log('Trying to get some more data...');
  // returns a 404 if it doesn't exist
  return get(`https://jsonplaceholder.typicode.com/comments/501`)(state)
    .catch(error => {
      console.log('But failing with...', error.response.status);

      // create the option
      return post(`https://jsonplaceholder.typicode.com/comments`, {
        body: {
          // code: state.references[0].x.toLowerCase().trim(),
          // value: state.references[0].x,
        },
        // header: { y: state.references[1].y },
      })(state);
    })
    .then(result => result)
    .finally(result => result);
});
  1. This is a small thing, but once you’re inside that fn block and making your post to “create the option” you can access parts of state directly, rather than through a function. When using these helper operations (like get, post, or createPatient) directly, OpenFn’s “magic” is knowing when to evaluate state. But inside a custom fn block you’re on your own… so if you define state on line 4, you’ll be plucking out state.references of that state when you ask for it later in your code block.

This last point is definitely a subtle one, but the guiding principal is that inside an open fn :wink: block, you’re writing code and doing exactly what you want… no magic (or interference) from core.

I guess my java experience got the better of me.
Thanks, it’s working brilliantly.

1 Like