-1

I just started learning node.js and am trying to figure out how promises work.

I'm already familiar with async/await and am using axios to fetch data. Once the data is fetched, I want to write the data to a file and when that's done, log successful to the console.

To learn more about promises, I want to make my own that logs ++ to the console and then integrate that promise into the above.

So I wrote this, but when I run it with node, it only logs ++. I tried some variants, but don't understand what's happening.

const second = async () => {
  console.log('++')
}

const processData = async () => {  
  const req = await axios.get('http://localhost:5004/swagger');
  let reqJson = JSON.stringify(req.data);
  fs.writeFile('newSwagger.json', reqJson, (err) => {
    if (err) throw err;
    console.log('successful');
  });
}

let firstPromise = new Promise (function (resolve, reject) {
  second(() => {
    resolve(processData());
  });
});

firstPromise.then(function() {
  second();
});

Why does the above code not produce the following output?

++
successful
++
ccchoy
  • 704
  • 7
  • 16
B1sman
  • 7
  • 3
  • The code in the question will throw a number of syntax errors. You will also find coding easier if you use proper indentation, so that blocks are easily recognizable at a glance. – CertainPerformance Oct 31 '22 at 00:39
  • `second()` is a function that takes no arguments. So passing a callback to it will NEVER call that callback, thus `firstPromise` will never resolve. – jfriend00 Oct 31 '22 at 02:49
  • Could you help describe what your desired/expected output is? – ccchoy Nov 02 '22 at 21:28

1 Answers1

0
const axios = require("axios");
const fs = require("fs").promises;

const second = async () => {
  console.log('++')
}

const processData = async () => {  
  const req = await axios.get('http://google.com');
  let reqJson = JSON.stringify(req.data);

  try {
    await fs.writeFile('newSwagger.json', reqJson);
    console.log('succesful');
  } catch (e) {
    throw e;
  }
}

let firstPromise = new Promise (function (resolve, reject) {
  second().then(processData).then(resolve);
});

firstPromise.then(second)
  .then(() => console.log('finished'));

results in

++
successful
++
finished

Explanations

second is a parameterless function that returns a promise. It isn't itself a promise. This means that when you're doing second(() => resolve(processData())), you're never actually invoking the processData function. You're just executing the second function and handing it a function that would run processData but instead it never executes the passed in function as something like this would:

const second = async (callback) {
  callback()
}

Also the async keyword for second is unnecessary since you're not using an await within. The async keyword basically is syntactic sugar which wraps the function into returning a promise kind of like:

const second = () => {
  console.log('++')
  return new Promise();

so in my corrected example, that's why I can suddenly do second().then(doSomething) however because there's nothing awaited within, it's the exact same as just second() followed by doSomething().

Also, the resolve inside of new Promise((resolve, reject) => ...) is kind of like setting a return, but it doesn't necessarily wait for anything. So if you want the second '++' to wait until processData is completely done and 'successful' is logged, you need to chain off the processData's returned promise like .then(processData).then(resolve).

Finally if you do the above, you may still notice that you don't see your 'successful' string printed - or well you might sometimes and at unexpected times. This is because you've also added callbacks into the mix along with promises and async/await. the ultimate effect being that your console.log('successful') will run at some point but you have nothing waiting for it nor chained after it. You could promisify the call to fs.writeFile yourself but you could also just use the built-in promise version of node's fs module - see this for more.

If it helps focus only on how the promises work(without async/await and callbacks also), here's a version with only promises to achieve the same resulting output:

const axios = require("axios");
const fs = require("fs").promises;

const second = () => {
  console.log('++')
}

const processData = () => {  
  return new Promise(
    resolve => axios.get('http://google.com').then((req) => {
        let reqJson = JSON.stringify(req.data);
        return reqJson;
    }).then((reqJson) => {
        fs.writeFile('newSwagger.json', reqJson).then(resolve);
    }).then(() => console.log('successful'))
  );
}

second();
processData().then(() => {
    second();
    console.log('finished')
})
ccchoy
  • 704
  • 7
  • 16