Answered by:
How to make WinJS appendTextAsync wait until file not busy?
Question
-
I have code like this for logging in my WinJS app:
var log_file = null; function setupLogFile() { 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 }); }); } setupLogFile(); // ... // 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.Wednesday, September 17, 2014 2:47 PM
Answers
-
Found a solution with the help of good folks over at StackOverflow (@Bergi). Slight reorganization of the function to initially store the file creation promise in log_file, then after every log_fn call store the appendTextAsync promise back into log_file so everything gets queued up appropriately:
function startLogFile() { if (log_file) { WinJS.Utilities.stopLog(); log_file.done(function (file) { /* close file handle somehow? */ }); log_file = null; } 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 }); }); } }); WinJS.log && WinJS.log("INITIALIZED LOG FILE", "myApp", "info"); };
- Marked as answer by amHammock Wednesday, September 17, 2014 6:08 PM
Wednesday, September 17, 2014 6:06 PM
All replies
-
Found a solution with the help of good folks over at StackOverflow (@Bergi). Slight reorganization of the function to initially store the file creation promise in log_file, then after every log_fn call store the appendTextAsync promise back into log_file so everything gets queued up appropriately:
function startLogFile() { if (log_file) { WinJS.Utilities.stopLog(); log_file.done(function (file) { /* close file handle somehow? */ }); log_file = null; } 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 }); }); } }); WinJS.log && WinJS.log("INITIALIZED LOG FILE", "myApp", "info"); };
- Marked as answer by amHammock Wednesday, September 17, 2014 6:08 PM
Wednesday, September 17, 2014 6:06 PM -
Nice to see the solution, should help other community members.
--James
<THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
Thanks
MSDN Community Support
Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.Friday, September 19, 2014 1:51 AMModerator