Returning [Object Promise]

I felt like I went through the async-await section well but there is one topic I can not seem to grasp and have not been able to find out myself after days of the forum and trial/error. It is fairly simple, I want to return an async function with a variable. I know we test with ‘console.log’ as we navigate through linked promises and such and although it works, I can not seem to get to link it to a variable to use later in the code. As an example, I am using the code lesson from the first section of async-await (see code and link below)
Lesson Page

async function readFiles() {
  let secondSentence = await promisifiedReadfile('./file2.txt', 'utf-8');
  let firstSentence = await promisifiedReadfile('./file.txt', 'utf-8');
  console.log("READFILES: "+firstSentence);
  return firstSentence;
}

function printSentence(sentence) {
  console.log(sentence);
  return sentence;
}

const testingVar = readFiles().then(data => printSentence(data));
console.log("TESTINGVAR: "+testingVar);

This is a testing case for the goal I am trying to get to. When we run this in node, the console.log statements work for all except the ‘last’ one with "TESTINGVAR: ". It is confusing because both inside the readFiles() function and the printSentence function we get the correct answer logged, but when we try to save it down to a variable and then print it…we get the [object promise] return. Can anyone add some clarity or point me in the right direction as to where/why this is happening?

I thought async functions returned a promise that resolves to what’s after the return instead of actually returning what’s after the return keyword. So an async looks like a regular function, but doesn’t exactly act like one.
I think that’s why testingVar is a promise here.

I thought since there is a function for the ‘.then’ statement that returns the sentence that would do the trick. How does one save down the results of a promise then in general? I feel as though I have missed something big to not understand this piece. For example, if we have a promise statement that pulls a login token from an account… there must be a way to save down the result itself as just knowing that the token was received is half of the ask.

The main thing here is to understand blocking vs. non-blocking calls.

If I have a blocking call foo(), I’m telling the compiler/interpreter that I want that run before anything that comes after it.

foo() //is blocking call
bar()

would run foo(), bar() in that order.

If it’s non-blocking, then all bets are off. Compilers will try to optimize how they see fit and there’s no predictable way of knowing the order of operations. Since an async call usually do expensive i/o operations, they’re usually going to run after the fact.

If I have two non-blocking calls bar() and baz()

bar()
baz()

they can either run bar() baz(), or baz(), bar(). Whichever the compiler/interpreter chooses (not up to us).

If you wanted to enforce the execution of one before the other you would have to specify it.
You can wrap this whole code in an await function and say

async wrapper() {
  //now it's a blocking call
  const testingVar = await readFiles().then(data => printSentence(data)); 
  console.log("TESTINGVAR: "+testingVar);
}
wrapper() //but note that wrapper is still non-blocking, since it's async

There’s a lot of resources for this depending how deep you want to go. My go-to would be operating systems references and then connect that to js, but something more js specific: Overview of Blocking vs Non-Blocking | Node.js …notice the difference between

readFileSync() and readFile() //implicitly readFileAsync

More heavy: https://www.cs.rutgers.edu/courses/416/classes/fall_2009_ganapathy/slides/io.pdf

4 Likes

This is a better link since javascript is not my forte and I don’t want to miss any nuance on this tricky topic. This is more js specific (in general this is a great book series):

2 Likes