Kleber Germano
Kleber Germano

Reputation: 780

Curry function with the first one as an async function isn't working

I'm trying to curry a function but when the first one is async it throws the error function1(...) is not a function, however if I pass the async function as the last one it works fine.

Can anyone tell me why this is happening? and how to properly make a curry function that starts with a async function?

Thanks to anyone who take the time.


//This one is throwing the error: function1(...) is not a function
async function function1(path) {
 const fetchedElement = await fetchElement(path);
//(...)
  return (msg) => {
    console.log(msg);
  };
}

function1('somepath.html')('my message');

//This one works fine, properly returning other function
function function2(path) {
  return async (msg) => {
    const fetchedElement = await fetchElement(path);
  //(...)
    console.log(msg);
  };
}
function2('somepath.html')('my message');

Upvotes: 2

Views: 685

Answers (2)

danh
danh

Reputation: 62686

It depends on when the async work needs to get done. If you want the currying process to do the async work, then you can't invoke the currying function synchronously:

curryingFunction(paramA)(paramB)
                        ^ assumes curryingFunction is synchronous

Instead, use two statements by the caller, one to await the currying, the other to invoke...

const fetch = path => new Promise(resolve => setTimeout(() => {
  console.log('fetched ' + path)
  resolve()
}, 1000));

async function curryingFunction(path) {
  const fetchedElement = await fetch(path);
  return message => {
    console.log(message);
  }
}

async function someCaller() {
  // await to get a curried function, then invoke it
  let curried = await curryingFunction('some_path');
  curried('some message');
}

someCaller()

On the other hand, you might not need to do the async work in order to get the curried function. You probably don't. In that case, you can make the currying function synchronous, but have it return an async function that does the async work.

As a result, you'll get to use the fn()() syntax that you're probably used to using...

const fetch = path => new Promise(resolve => setTimeout(() => {
  console.log('fetched ' + path)
  resolve()
}, 1000));

function curryingFunction(path) {
  return async (message) => {
    const fetchedElement = await fetch(path);
    console.log(message);
  }
}

async function someCaller() {
  // here we can use the fn()() syntax that we're accustomed to
  await curryingFunction('some path')('some message')
}

someCaller()

Upvotes: 1

Mina
Mina

Reputation: 17604

As the first function is async You need to await it first, then call the second parameter.

//This one is throwing the error: function1(...) is not a function
async function function1(path) {
 const fetchedElement = await Promise.resolve(1);
//(...)
  return (msg) => {
    console.log(msg);
  };
}

(async () => {
try {
 (await function1('somepath.html'))('my message');
} catch(e) {
  console.log(e)
}
})()

Upvotes: 1

Related Questions