1

typescript async await doesn't work with the current senario dealing with the NODE js FS.

Following the code.

   public static FileExists(filePath: string): Promise<boolean> {
        return new Promise<boolean>(async (resol, reje) => {
            try {
                fs.accessSync(filePath, fs.F_OK);
                resol(true);
            }
            catch (e) {
                resol(false);
            }
        });
    }

     public static async CreateDirectory(name: string): Promise<boolean> {
    return new Promise<boolean>(async (resolve, reject) => {
        let dirExist: boolean = await FileManager.FileExists(name);
        try {
            if (!dirExist) {
                fs.mkdirSync(name);
            }
            resolve(true);
        } catch (e) {
            resolve(false);
        }

    });

  for (var i = 0; i < paths.length; i++) {
                var element = paths[i];
                fullPath += element + "/";
                let a = await FileManager.CreateDirectory(fullPath);
                console.log(fullPath);
            }

I have added the await in the foreach but the loop continues and I don't get value of a before the loop iteration , instead it gives all the values at the end.

Note: i can add the promise to all object that are present in the loop but the problem is that it calls every time either the file is present or not, if the file isn't present it tries to create the same directory multiple times or each of the time file exist is called.

What i want that it should check for file once and not found , it should create directory and afterward the directory existence would be true so it woill stop creating same directory multiple muyltiple times.

Peter Badida
  • 11,310
  • 10
  • 44
  • 90
Shan Khan
  • 9,667
  • 17
  • 61
  • 111
  • 5
    `await fs.accessSync(filePath, fs.F_OK);` makes no sense at all. As the name suggests, `fs.accessSync` is a synchronous function. – T.J. Crowder Dec 26 '16 at 15:04
  • 2
    Avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Dec 26 '16 at 15:05
  • 3
    Also you should [never pass an `async function` to a `Promise` constructor](http://stackoverflow.com/a/39409757/1048572) and [`forEach` does not work with `async function`s](http://stackoverflow.com/q/37576685/1048572) – Bergi Dec 26 '16 at 15:10
  • @T.J.Crowder thanks, i have changed it but still there is the same problem – Shan Khan Dec 26 '16 at 15:34
  • @Bergi i have changed and maintaining all the defered state now, would you please give an example to solve this question so i can better understand the antipattern – Shan Khan Dec 26 '16 at 15:37
  • i can add the promise in promise all though but the problem is that Create Directory calls the file exists all the iteration times and then create the directory again ang again, but i want that it should first call if no directory is created it should create the directory and then go for new iteration and check the file exist and go on as currently it checks multiple times and file doenst exist and try to create the same directoty multiple times. – Shan Khan Dec 26 '16 at 16:13
  • You should look into await/async and how they complement [Promises](https://stackoverflow.com/documentation/javascript/231/promises#t=20161226162809585885). You have some pretty deep misconceptions. – Madara's Ghost Dec 26 '16 at 16:27

1 Answers1

0

You need to properly promisify an asynchronous file system method, so you cannot use accessSync and mkdirSync (or you could use them, but then promises and async function would be pointless).

Instead, do

public static fileExists(filePath: string): Promise<boolean> {
    return new Promise<boolean>(async resolve => {
        fs.accessSync(filePath, fs.F_OK, err => {
            if (err) resolve(false);
            else resolve(true);
        });
    });
}

public static async createDirectory(name: string): Promise<boolean> {
    if (!await this.fileExists(name)) {
        await new Promise(async (resolve, reject) => {
            fs.mkdir(name, err => {
                if (err) reject(err);
                else resolve();
            });
        });
    }
    return true;
}

var fullPath = ""
for (var element of paths)
    fullPath += element + "/";
    let a = await FileManager.createDirectory(fullPath);
    console.log(fullPath);
}

However, notice that using fs.access to check before an action is not recommended. You should instead simply catch the error:

public static createDirectory(name: string): Promise<boolean> {
    return new Promise(async (resolve, reject) => {
        fs.mkdir(name, err => {
            if (err) reject(err);
            else resolve();
        });
    }).then(() => true, err => {
        if (err.code == "EEXIST") return false;
        else throw err;
    });
}
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • createDirectory seond one will return a promise with mkdir or will return from the then part ? – Shan Khan Dec 27 '16 at 11:25
  • It will return a promise from the `then` part that happens after the `mkdir` promise. It'll fulfill with `true` when it created a directory, `false` when the path already existed, and reject when an error happens. – Bergi Dec 27 '16 at 13:20