2

everyone I am working on some sort of image view application using node-webkit. I made a function to read dir inside the given location and search for the image files(*.jpg and *.png). Code I used is as follows:
app.js

    var fs = require("fs");
    var gui = require('nw.gui');
    var win = gui.Window.get();
    var directory;
    var db = require('diskdb');
    var path = require('path')
    db = db.connect("lib/collections", ['temp']);


        function chooseFile(name) {
        var chooser = $(name);
        scr = 0;
        chooser.change(function(evt) {
            directory = $(this).val();
            var asdf;
            console.clear();
            readDir(directory);
            $(this).val('').hide();
        });
    }


    function readDir(directory){
    c = 0;
    console.log("reading "+directory);
if(fs.statSync(directory).isDirectory() == true){
    fs.readdir(directory,function(err,files){
        if (err){
            console.log(err);
            return;
        }           
        var ext;
        files.forEach(function(file){
            console.log("Got what: "+file);
            var fulls = directory+"\\"+file;
            if(file.indexOf(".") != 0){
                if(path.extname(fulls) == ""){
                    console.log("Got a directory: "+file);
                    if(fs.statSync(fulls).isDirectory() == true){
                        readDir(fulls);
                    }
                }
                else{
                    console.log("Got a file: "+file);
                    if(checkExtension(file, 'jpg,png')){
                        scr++;
                        c = saveTemp(fulls,scr,file);
                    }
                }
            }
        });
        if(c == 1){
            loadgun();
        }
    });
}
  }


        function loadgun(){
    if(db.temp.count()!=0){
        for(i=1;i<=db.temp.count();i++){
            var asd = db.temp.findOne({'id':i});
            var theTempScript = $("#tmpl-imgholder").html();
            var theTemp = Handlebars.compile(theTempScript);
            $("#ContentWrapper").append(theTemp({"fulls":asd.file, "id":asd.id, "title":asd.title}));
        }
    }
}

  saveTemp = function(file,id, title) {
    var savedUser = db.temp.save({
        file:file,
        id:id,
        title:title 
    });
    return 1;

};


    function checkExtension(str, ext) {
        extArray = ext.split(',');
        for(i=0; i < extArray.length; i++) {
            if(str.toLowerCase().split('.').pop() == extArray[i]) {
                return true;
            }
        }
        return false;
    };


$(document).ready(function(){
if(db.temp.count() != 0){
   loadgun();
}
else{
    $('#blah').css('display','block');
    chooseFile('#blah');
}
});

index.html

<html>
.
.
.
<body>
<input type="file" nwdirectory id="blah" style="display:none"/>
    <script src="js/jquery.min.js"></script>
    <script src="js/app.js"></script>
    <script src="js/handlebars.js"></script>
    <script id="tmpl-imgholder" type="x-handlebars-template">
        <div class="image-container grid__item" data-id="{{id}}" data-src="{{fulls}}">
            <div class="cover" style="background:url({{fulls}})"  title="{{title}}"></div>
            <div class="info">
                <div class="title">{{title}}</div>
            </div>
            <div class="clear"></div>
        </div>
    </script>
</body>
</html>

Here i tried to load data using loadgun function. Its hangs the node webkit window. If I could know when the readDir function terminates then i could do load the required datas. If there is another way please do say. Thanks in advance.

Bibash Adhikari
  • 292
  • 4
  • 16

2 Answers2

0

the problem with readDir is that is asynchronous function , that is why you have to provide a callback. you can however use fs.readdirSync(path) which is synchronous , and then the code flows synchronously. a psoducode may look like this :

function readDirAsynch(dir){
 var files = fs.readdirSync(dir);
  for (var i in files){
    if (files[i] isDir){
      readDirAsynch(files[i]);
    } else if (myCondition){
    //do somehting
   }
  }
}    

needless to say , you know that the function is done when the next line after the function call is being executed

David Haim
  • 25,446
  • 3
  • 44
  • 78
0

Quick answer: You can use the synchrohous method fs.readdirSync(path) and everything should work just fine for you. You don't need to keep reading. https://nodejs.org/api/fs.html#fs_fs_readdirsync_path

My personal suggestion:

Since node is single threaded I would recommend you to keep using the asynchronous version but adding a callback to your method.

This means that your "readDir" method is going to be asynchronous too. You only need to add a callback parameter to your method. E.g.

readDir(dir, fnCallback) {
  ...
  fs.readdir(directory, function(err,files){

    ... doing cool stuff ...

    fnCallback();
  });
}

If you want to read more about writing asynchronous code maybe this guide can help you. http://callbackhell.com/

Also if you want to go further in the wonderful asynchronous world you can take a look to 'Promises' https://www.npmjs.com/package/node-promise, 'Future' https://www.npmjs.com/package/async-future, 'Async' https://www.npmjs.com/package/async and have more fun than you have ever imagined before.

Aebsubis
  • 1,921
  • 18
  • 19