Ian
Ian

Reputation: 354

readfile one by one with async / await

The code is following:

function readfile(file) {
   var readline = require('readline');
   var fs = require('fs');
   var fReadAD = fs.createReadStream(file,{ encoding: 'utf8'});
   var objReadlineAD = readline.createInterface({
      input: fReadAD
   });
   objReadlineAD.on('close', (line)=>{
      return new Promise(function(){
          console.log('file:'+file)
      });
   });
}
(async () => {
   await readfile('./import/1.xls')
   await readfile('./import/2.csv')
})();

Why the output is

file:./import/2.csv
file:./import/1.xls

I thougth it should be

file:./import/1.xls
file:./import/2.csv

I have used await in async. Could someone tell me what's wrong? thx!

Upvotes: 1

Views: 1840

Answers (1)

jfriend00
jfriend00

Reputation: 708156

Your return new Promise() is not returning from readFile(). Because asynchronous operations in node.js are non-blocking, the readfile() function returns immediately (with no return value) and then the file event occurs sometime later (after the function has already returned). So your readFile() function returns nothing, therefore await has no promise to actually wait on.

This shows that you need some basic education/reading on how asynchronous events and operations work in node.js.

The return new Promise() you do have just goes back into the readLine library file system event handling code and is ignored so it doesn't do anything useful. It's not actually returned to anyone who's looking for a promise.

So, since you aren't actually returning anything and you aren't actually await ing anything, your two async operations proceed in parallel and it is indeterminate which one completes first. It will likely depend upon the details of how long each readFile() takes and it's just a race to see which one finishes first. You have not controlled their order of execution.

The order of events is this sequence:

  1. Start first readFile() operation. It returns no return value and the file operations in it proceed as asynchronous code/events.
  2. You await undefined which doesn't wait for anything.
  3. Start second readFile() operation. It returns no return value and the file operations in it proceed as asynchronous code/events.
  4. You await undefined which doesn't wait for anything.
  5. One of the two readFile() operations generates its close event (whichever one happens to finish first).
  6. The other readFile() operations generates its close event.

You can get readFile() to actually return a promise that is connected to when it completes which you can then await like this:

const fs = require('fs');
const readline = require('readline');

function readfile(file) {
   return new Promise(function(resolve, reject) {
       var fReadAD = fs.createReadStream(file,{ encoding: 'utf8'});
       var objReadlineAD = readline.createInterface({
          input: fReadAD
       });
       objReadlineAD.on('close', () => {
           console.log('file:'+file)
           resolve();
       }).on('error', reject);
   });
}

(async () => {
   await readfile('./import/1.xls')
   await readfile('./import/2.csv')
})();

Upvotes: 3

Related Questions