4

Let's say I have this code:

const myFunction = async => {
  const result = await foobar()
}

const foobar = async () => {
  const result = {}
  result.foo = await foo()
  result.bar = await bar()
  return result
}

And I want this:

const myFunction = () => {
  const result = foobar()
}

I tried to wrap foobar like this:

const foobar = async () => {
  return (async () => {
    const result = {}
    result.foo = await foo()
    result.bar = await bar()
    return result
  })()
}

But this still return a promise

I can't use .then in myFunction, I need that foobar returns the result variable instead a promise.

The problem is that myFunction is an async function and it will return a promise but It should return undefine I need to get rid of async in myFunction.

Edit: as Sebastian Speitel said, I want to convert myFunction to sync

Edit 2: to Shilly, I am using nightwatch for end2end test, nightwatch will call myFunction() if there are no errors in the execution of the function it will run perfectly, if there's an error then nightwatch's virtual machines will run forever instead stop, this problem happens if the called function is async.

Shilly
  • 8,511
  • 1
  • 18
  • 24
José Sánchez
  • 159
  • 1
  • 2
  • 11
  • 2
    To make async function sync again you either need to use a callback or a while(true) to prevent code execution until the promise resolves – Sebastian Speitel Dec 03 '18 at 12:23
  • What do you mean by getting rid of async? Do you want your code to stop all execution until `foo()` and `bar()` are finished? What is inside the `foo()` and `bar()` functions? Can you rewrite those to not return Promises? – Kokodoko Dec 03 '18 at 12:28
  • To rewrite your function in a sync mode you should make sync the functions _foo()_ and _bar()_. If those functions are an external API, you should check if there is a sync version. Be aware that if you rewrite in a sync mode it will be sensible slower. – Mario Santini Dec 03 '18 at 12:29
  • Can you explain more of the context of Why this has to be removed? Since what you're asking is rather peculiar, usually people want it the other way around, so it might be an x/y question. We'll need to know what foobar() does to know if it can be turned into a callback. – Shilly Dec 03 '18 at 12:33
  • @Shilly edited, thanks – José Sánchez Dec 03 '18 at 12:38

5 Answers5

2

To change an asynchronous function into a normal synchronous function you simply have to drop the async keyword and as a result all await keywords within that function.

const myFunction = async () => {
    const result = await foobar();
    // ...
    return 'value';
};

// becomes

const myFunction = () => {
    const result = foobar();
    // ...
    return 'value';
};

You should however keep one simple rule in mind.

  1. You can't change a asynchronous function into a synchronous function if the return value depends on the value(s) of the resolved promise(s).

This means that functions that handle promises inside their body, but from whom the return value doesn't depend on those resolved promises are perfectly fine as synchronous functions. In most other scenarios you can't drop the asynchronous behaviour.

The following code gives you an example for your situation, assuming the return value of myFunction doesn't depend on the resolved promise.

const myFunction = () => {
    const result = foobar();

    result.then(data => doSomethingElse(data))
          .catch(error => console.error(error));

    return 'some value not dependent on the promise result';
};

If you want to learn more about promises I suggest checking out the promises guide and the async/await page.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
1

Have you looked into using .executeAsync() and then having the promise call the .done() callback? That way it should be possible to wrap foobar and just keep either the async or any .then() calls inside that wrapper.

My nightwatch knowledge is very stale, but maybe something like:

() => {
  client.executeAsync(( data, done ) => {
    const result = await foobar();
    done( result );
  });
};

or:

  () => {
    client.executeAsync(( data, done ) => foobar().then( result => done( result )));
  };
Shilly
  • 8,511
  • 1
  • 18
  • 24
  • If it doesn't work with .executeAsync function change to .perform function, just changed .executeAsync for .perform and it works. – José Sánchez Dec 12 '18 at 15:42
0

Any function marked with async will return a Promise. This:

const foobar = async () => {
  return 7;
}

Will a return a Promise of 7. This is completely independent of wether the function that calls foobar is async or not, or uses await or not when calling it.

So, you're problem is not (only) with myFunction: is foobar using async which forces it to always return a Promise.

Now, said that, you probably can't achieve what you want. Async-Await is only syntax sugar for promises. What you're trying is to return a synchronous value from an asynchronous operation, and this is basically forbidden in javascript.

Sergeon
  • 6,638
  • 2
  • 23
  • 43
0

You're missing very important understanding here between the synchronous and asynchronous nature of the code.

Not every async function can be converted to synchronous function. You can use callback pattern instead of await/async, but I doubt that would be useful to you.

Instead I would recommend you just use await, as in your first code example, and leave functions as async, it shouldn't harm your logic.

Daniel Kmak
  • 18,164
  • 7
  • 66
  • 89
0

Check this out

    function foo(){
      return 'foo'
    }
    function bar(){
      return 'bar'
    }
    const foobar = () => {
        return new Promise((resolve)=>{
          let result = {}
          result.foo = foo()
          result.bar = bar()
          return resolve(result)
        })
    }

    const myFunction = () => {
      const result = foobar()
      let response = {}
      result.then(val=>{
        response = Object.assign({}, val);
        return response
      });
    }

    var test = myFunction()
    console.log(test)
decodedxclusive
  • 401
  • 4
  • 8