user206481
user206481

Reputation: 258

WinJS how to make appendTextAsync wait for file available

I have code like this for logging in my WinJS app:

function setupFileLog() {
    var logFn = function (message, tag, type) {
        if (!log_file) return; // log_file is global, setup below with a StorageFile object
        Windows.Storage.FileIO.appendTextAsync(log_file, tag + ' ' + type + ': ' + message)
            .done(null, function (error) {
                // I have a breakpoint here to catch the error
                var msg = error.detail.message;
                }
            });
    };

    app_folder.createFolderAsync('logs', Windows.Storage.CreationCollisionOption.openIfExists)
       .then(function (logfolder) {
           var now = new Date();
           var logfilename = config.device + "_" + now.toDateString() + ".log";
           return logfolder.createFileAsync(logfilename, Windows.Storage.CreationCollisionOption.openIfExists)
       })
       .done(function (file) {
           log_file = file; // save in global var
           WinJS.Utilities.startLog({ tags: "myApp", action: logFn });
       });
}

setupFileLog();

// ...
// do stuff and log things
// ...

WinJS.log && WinJS.log('I did some stuff', 'myApp','info');
WinJS.log && WinJS.log('I got an error: '+error, 'myApp','error');

Intermittently, I get an error in my logFn "The process cannot access the file because it is in use by another process" or "Access is denied". I think that multiple calls to WinJS.log are colliding because of the async nature of the appendText call and trying to get a handle to the log file before the previous logging call is finished writing.

Can I make appendTextAsync wait until the log file is not in use? I can't find any calls to check if the file is busy. I think there is a way to make appendTextAsync act in a synchronous way but I'd like to avoid doing that in all cases since this is just an intermittent case.

Upvotes: 0

Views: 473

Answers (1)

Bergi
Bergi

Reputation: 665100

You could make a chain of calls that is automatically executed in sequence:

function setupFileLog() {
    var log_file = app_folder.createFolderAsync('logs', Windows.Storage.CreationCollisionOption.openIfExists)
   .then(function (logfolder) {
        var now = new Date();
        var logfilename = config.device + "_" + now.toDateString() + ".log";
        return logfolder.createFileAsync(logfilename, Windows.Storage.CreationCollisionOption.openIfExists)
    });

    WinJS.Utilities.startLog({
        tags: "myApp",
        action: function log_fn(message, tag, type) {
             log_file = log_file.then(function(file) {
                 return Windows.Storage.FileIO.appendTextAsync(file, tag + ' ' + type + ': ' + message)
                 .then(function() {
                     return file;
                 }, function (error) {
                    // I have a breakpoint here to catch the error
                    var msg = error.detail.message;
                    return file; // for further logs, or
                    throw error; // go stop logging
                 });
            });
        }
    });
}

Every call to the log_fn does chain another appendTextAsync call onto the log_file promise. The bonus is that calls are already chained when the log file is not yet created, instead of simply dropping log lines.

Upvotes: 3

Related Questions