0

Let a function which returns a promise:

async function foo() {
  return await new Promise((res, rej) => {
    fetch('https://jsonplaceholder.typicode.com/todos/1')
          .then(res => res.json())
          .then(data => res(data))
          .catch(err => rej(err))
  })
}

In order to reuse the returned data I can think something like:

(async function() {
    data = await foo().catch(err => console.log('err: ', err))
    fnc1(data)
    fnc2(data)
    ...
    fncn(data)
})();

or something like:

foo().then(data => {
                fnc1(data)
                fnc2(data)
                ...
                fncn(data)
              }
        )

So always I have to go back in my code find the function or callback which gets the data returned by the promise and include any new function that I want to the appropriate block.

I was wondering if there is any smarter way to achieve the same result in javascript. I know that something like the following won't work:

var dataFromPromise
foo().then(data => dataFromPromise = data)
console.log(dataFromPromise) //undefined if called before foo runs
jeremyTob
  • 131
  • 10
  • 2
    wrapping `fetch` in `new Promise` is the [explicit promise construction ant-pattern](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it) since `fetch` already returns a promise – charlietfl Aug 04 '18 at 18:43
  • Can store a promise and use `then()` on it as often or whenever you want – charlietfl Aug 04 '18 at 18:44
  • Change `return await new Promise(...)` to `return fetch()`. There is no reason for `aysnc` or `await` in this function. Just return the promise you already have. `return await xxxx` is an anti-pattern as is wrapping an existing promise in another manually created promise. – jfriend00 Aug 04 '18 at 22:35
  • You may find some of the options here useful: [How to chain and share prior results with promises](https://stackoverflow.com/questions/28714298/how-to-chain-and-share-prior-results-with-promises/28714863#28714863) as it seems this is basically what you're asking. – jfriend00 Aug 04 '18 at 22:36

2 Answers2

1

Store the promise once somewhere:

 const dataPromise = foo();

Then whenever you need to call a function that uses it:

 dataPromise.then(fnc1)

Or inside async functions:

 fnc1(await dataPromise)
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
1

 Don't wrap promises inside promises

fetch already returns a Promise, so there is no need to wrap it into another Promise. Instead of:

async function foo() {
  return await new Promise((res, rej) => {
    fetch('https://jsonplaceholder.typicode.com/todos/1')
          .then(res => res.json())
          .then(data => res(data))
  })
}

Do:

function foo(){
  return fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then(res => res.json())
  .then(data => res(data))
  .catch(err => rej(err))
}

 Reusing promises

Once you have a Promise, should it be pending, rejected or fulfilled, you can reuse it again and again, and if it is resolved it will always give the returned value. So instead of:

foo().then(data => {
    fnc1(data)
    fnc2(data)
    ...
    fncn(data)
  }
)

You can just do:

const myPromise = foo();

myPromise.then(data => fnc1(data));

// some code

myPromise.then(data => fnc2(data));

// more code

myPromise.then(data => fnc3(data));

And you can be sure that fnc1 and the others won't get call until the promise resolves.

Now, this sure is good, but doesn't solve all the related problems, and a lot of bad things can still happen with this approach. To tackle all the possible ways to handle and reuse promise is something too wide for a SO answer.

A pretty good resource about this topic is:

http://2ality.com/2017/08/promise-callback-data-flow.html

Sergeon
  • 6,638
  • 2
  • 23
  • 43