0

I have two functions. function1() takes more time to complete than function2() because it does a fetch request. I need them to be launched in this order, but the results of function2() are the first that are displayed on the HTML DOM. So, I tried to resolve this with promises. I made the first function a variable, and created the following code:

let promise1 = function1() {
  fetch()
   .then(do x)
   .then(display x to HTML DOM)
  return 0;
};

function2(a) {
  // use the a;
  // display some things to the HTML DOM based on `a`
}

promise1.then((a) => {
      function2(a);
    });

Originally, these two functions don't need to interact with one another, but in order to make this work with promises, I created an artificial need by using that return statement. However, this doesn't work: I get a TypeError: promise1.then is not a function error. I skimmed through the 'Learn more' webpage, but those scenarios don't apply here.

I am quite new to JS and a neophyte to promises. Am I missing something?

  • `function1()` does a fetch request that takes some time to complete. I need to wait for this fetch before launching `function2()`. Isn't this async? –  Nov 27 '18 at 09:06
  • So the problem is just that the output of function 2 needs to come after output of function 1 in the DOM? Does function 2 use variables from function 1? – Patrick Nov 27 '18 at 09:07
  • 1
    Please show a more realistic version of your `function1` which demonstrates how exactly it uses async processing. – deceze Nov 27 '18 at 09:12
  • @deceze done. Patrick, the second function doesn't use any variables from the first. –  Nov 27 '18 at 09:15
  • 1
    You just need `return fetch()...` in your first code block. Why are your returning 0? That will run sync – Liam Nov 27 '18 at 09:15

2 Answers2

1

To address this, you will need to ensure function1 returns a promise object.

By returning a promise object, this allows you to "chain" subsequent .then() handlers off of calls to that function (ie promise1) as you are trying to do.

So in the case of your specific problem, you would want to do something like this:

let promise1 = function1() {
    return fetch('/some/url').then(function (response){
        // Do response processing logic here
        return response; 
    }).then(function (data)  {
       //Chain any other data/response processing
       return data;
    });
};

The key thing to remember here is to return the call to fetch, as well as return data in each then handler that you chain to the call to fetch.

Hope that helps!

Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
1

You just need to return the promise returned from fetch in your first code block:

let promise1 = function1() {
  return fetch()
   .then(do x)
   .then(() => {
        //returns also need to be async
        return 0;
    });

  //don't do this
  // return 0;
  // return inside the then() above
};

function2(a) {
  // use the a;
  // display some things to the HTML DOM based on `a`
}

promise1.then((a) => {
      function2(a);
    });

To explain this in greater detail; Your fetch runs async. So any subsequent functions will not wait (block). fetch returns a Promise that allows you to chain subsequent functions when the async function finishes. So to run anything after fetch you need to consume the Promise that fetch returns. then is a function of the Promise object, not fetch itself, to consume the promise (call then on the promise object) you need to return it first, hence return fetch().... How do I return the response from an asynchronous call? goes into this in detail

Liam
  • 27,717
  • 28
  • 128
  • 190
  • A modified version of this answer solved my issue. Since the second function, as I mentioned, doesn't interact at all with the first (I used that `return` artificially), I made the following code: `promise1().then(() => {function2();});`. Together with adding a `return` before my fetch in the first function, this did the trick, apparently. –  Nov 27 '18 at 09:28
  • Yep, you could shorten that further with `promise1().then(function2);` if you really wanted to – Liam Nov 27 '18 at 09:30
  • If you want to return a value form an async function that return needs to be in an async function. The OP was trying to `return 0` after the async function had fired. See [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Liam Nov 27 '18 at 09:32
  • @Liam, so let me get this straight: the `return` before the `fetch` is needed to pipe the promise returned by the fetch to the second function and, although that function doesn't need that promise, this way, it will display the content in order? –  Nov 27 '18 at 09:38
  • 1
    I've added my comment into the answer @wombattrash – Liam Nov 27 '18 at 09:49