pvgdev
pvgdev

Reputation: 157

Returning values from Javascript Promise chain

Modern JS/Promise newbie here. I'm having trouble finding the answer to a simple question, despite the overwhelming amount of content on this subject.

I believe I have a decent understanding of JS Promises (thanks to various sources, including mdn and https://spin.atomicobject.com/2016/02/16/how-javascript-promises-work/)

I have consumed and produced Promises regularly in their simplest form, however I keep stumbling on methods in my inherited projects with the following pattern:

const doAsyncOp = () => 
  $http.get(uri)
    .then(
      value => value,
      reject => //... 
    );

My big question is: What happens when you simply return a value from your success handler? I need to consume this method, and need access to 'value' in the client code. Is this technically unhandled? Should I rewrite the implementation?

Upvotes: 1

Views: 5490

Answers (3)

Yonglin Li
Yonglin Li

Reputation: 1

I think you can use async and await for the resolved values.

function delay(t, v) {
    return new Promise(resolve => {
        setTimeout(resolve.bind(null, v), t);
    });
}

async function(){
    await myData = delay(1000, 1000);

    console.log(myData);
}

Upvotes: 0

jfriend00
jfriend00

Reputation: 708036

My big question is: What happens when you simply return a value from your success handler?

When you return a value from a .then() handler, that value becomes the resolved value of the parent promise chain: So, in this code:

// utility function that returns a promise that resolves after a delay
function delay(t, v) {
    return new Promise(resolve => {
        setTimeout(resolve.bind(null, v), t);
    });
}

function test() {
    return delay(100, 5).then(val => {
        // this return value becomes the resolved value of the promise chain
        // that is returned from this function
        return 10;
    });
}

test().then(result => {
    // logs 10
    console.log(result);
});

When you run it, it will log 10 because of the return 10 in the .then() handler.

There are four possibilities from a .then() handler:

  1. Return a regular value such as return 10 or return val. That value becomes the resolved value of the promise chain. If no value is returned (which in Javascript means the return value is undefined), then the resolved value of the promise chain is undefined.

  2. Return a promise that ultimately resolves or is already resolved. This promise is added to the chain and the promise chain takes on the resolved value of that promise.

  3. Return a promise that ultimately rejects or is already rejected. This promise is added to the chain and the promise chain takes on the rejected reason of the returned promise.

  4. Throw an exception. If an exception is thrown inside the .then() handler, then the .then() infrastructure will catch it and turn the promise chain into a rejected state with the reject reason set to the value that is thrown. So, if you do throw new Error("User not found") inside a .then() handler, then that promise chain will be rejected with that error object as the reject reason.


In your specific code:

const doAsyncOp = () => 
  $http.get(uri)
    .then(
      value => value,
      reject => //... 
    );

There is no reason for the value => value. value is already the resolved value of the promise, you do not need to set it again.

And since the fat arrow function automatically returns any single statement, you're already returning the promise from $http.get().then() in your doAsyncOp() function. So, you can just do:

const doAsyncOp = () => $http.get(uri);

doAsyncOp().then(result => {
   // handle the result here
}).catch(err => {
   // handle error here
});

Upvotes: 4

Mark
Mark

Reputation: 92461

To get this to the client code, just return the promise from your function:

const doAsyncOp = () => $http.get(uri)

then in your client you can use:

doAsyncOp()
.then(value => {
    // use value
}
.catch(err => { /* error */  }

Upvotes: 1

Related Questions