writing text file in suspend state event handler in windows 8 html5 - javascript

i am trying to write a text file when suspend event is fired i.e inside winjs.application.oncheckpoint event handler.
i am writing my object as JSON text.
here is the code:
applicationData.localFolder.createFileAsync("dataFile.txt", Windows.Storage.CreationCollisionOption.replaceExisting).then(function (sampleFile) {
var stringData = "";
var i;
for (i = 0 ; i < myData.objData.length - 1 ; i++) {
stringData += '{"title":"' + myData.objData[i].title + '","challange":"' + myData.objData[i].challange + '"},\n';
}
stringData += '{"title":"' + myData.objData[i].title + '","challange":"' + myData.objData[i].challange + '"}';
stringData = "[" + stringData + "]";
return Windows.Storage.FileIO.writeTextAsync(sampleFile, stringData);
}).done(function () { });
but windows app closes before writing anything into the text file.
I called args.setPromise() and passed the above code as a function parameter but same problem persists.
PS: i don't know how to do it asynchronously correctly.
please help.

like Phil has commented, remove .done() will fix it.
This is because done() does not return anything whereas then() returns chained promise. That is the reason nothing is getting called.
It is also recommended to save your application data as soon as it changes or at some intervals and not wait for the suspend event to save everything. Suspend event gives time of 5s. otherwise, the app is terminated as per msdn documentation here.
"If an app does not return from the suspending event within 5 seconds, Windows assumes that the app has stopped responding and terminates it"
app.oncheckpoint = function (args) {
app.sessionState.history = nav.history;
args.setPromise(Windows.Storage.ApplicationData.current.localFolder.createFileAsync
("dataFile.txt", Windows.Storage.CreationCollisionOption.replaceExisting).then(function (sampleFile) {
var stringData;
// code to set stringData.
return Windows.Storage.FileIO.writeTextAsync(sampleFile, stringData);
}));
};

Just event.setPromise(applicationData.localFolder.createFileAsync ...)
Then the suspend will wait until your promise finished. Remove the .done

Related

Chrome App: Cannot retrieve file load status

My Chrome app has a function that asks for a file to be loaded by another function, checks that the function has set a flag signifying success (External.curFile.lodd), then attempts to process it. My problem is that the flags are not set the first time I call the function, but when I call it a second time the flags are already set.
I had a feeling this has to do with Chrome file functions being asynchronous, so I had the first function idle for a bit while the file loads. The first load never succeeds, no matter how long I wait, but the second load always does!
Calling Function:
function load_by_lines_from_cur_dir( fileName, context ){ // determine the 'meaning' of a file line by line, return last 'meaning', otherwise 'null'
var curLineMeaning = null;
var lastLineValid = true;
External.read_file_in_load_path(fileName); // 'External' load 'fileName' and reads lines, REPLacement does not see this file
// This is a dirty workaround that accounts for the fact that 'DirectoryEntry.getFile' is asynchronous, thus pre-parsing checks fail intil loaded
var counter = 0, maxLoops = 10;
nuClock();
do{
sleep(500);
counter++;
preDebug.innerText += '\r\nLoop:' + counter + " , " + time_since_last();
}while( !External.curFile.lodd && (counter < maxLoops) ); //idle and check if file loaded, 5000ms max
preDebug.innerText += '\r\nLoaded?:' + External.curFile.lodd;
preDebug.innerText += '\r\nLines?:' + External.curFile.lins;
if( External.curFile.lodd ){ // The last load operating was successful, attempt to parse and interpret each line
// parse and interpret lines, storing each meaning in 'curLineMeaning', until last line is reached
while(!External.curFile.rEOF){
curLineMeaning = meaning( s( External.readln_from_current_file() ), context);
preDebug.innerText += '\r\nNext Line?: ' + External.curFile.lnnm;
preDebug.innerText += '\r\nEOF?: ' + External.curFile.rEOF;
}
} // else, return 'null'
return curLineMeaning; // return the result of the last form
}
which calls the following:
External.read_file_in_load_path = function(nameStr){ // Read the lines of 'nameStr' into 'External.curFile.lins'
External.curPath.objt.getFile( // call 'DirectoryEntry.getFile' to fetch a file in that directory
nameStr,
{create: false},
function(fileEntry){ // action to perform on the fetched file, success
External.curFile.name = nameStr; // store the file name for later use
External.curFile.objt = fileEntry; // store the 'FileEntry' for later use
External.curFile.objt.file( function(file){ // Returns 'File' object associated with selected file. Use this to read the file's content.
var reader = new FileReader();
reader.onload = function(e){
External.curFile.lodd = true; // File load success
};
reader.onloadend = function(e){
//var contents = e.target.result;
// URL, split string into lines: http://stackoverflow.com/questions/12371970/read-text-file-using-filereader
External.curFile.lins = e.target.result.split('\n'); // split the string result into individual lines
};
reader.readAsText(file);
External.curFile.lnnm = 0; // Set current line to 0 for the newly-loaded file
External.curFile.rEOF = false; // Reset EOF flag
// let's try a message instead of a flag ...
/*chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});*/
} );
},
function(e){ External.curFile.lodd = false; } // There was an error
);
};
This app is a dialect of Scheme. It's important that the app knows that the source file has been loaded or not.
I didn't read through all of your code, but you can't kick off an asynchronous activity and then busy-wait for it to complete, because JavaScript is single threaded. No matter what's happened, the asynchronous function won't be executed until the script completes its current processing. In other words, asynchronous does not imply concurrent.
Generally speaking, if task A is to be performed after asynchronous task B completes, you should execute A from the completion callback for B. That's the straightforward, safe way to do it. Any shortcut, to achieve better responsiveness or to simplify the code, is going to have dependency or race-condition problems, and will require lots of horsing around to get right. Even then, it will be hard to prove that the code operates correctly on all platforms in all circumstances.

How can I run a function after another is done in D3.js?

I am using d3.js to draw several bars. After the drawing is done, I want to change the color of selected bars, but it always fails. It seems drawBars() and updateColor() are called at the same time.
function redraw(data){
drawBars(data);
updateColor();
}
How can I ensure drawBars() is done before the updateColor() is called?
At first, I added the update function code at the end of drawBar, it didn't work. Later, I moved it to end of the redraw function, it didn't work either.
This is specific code:
function drawBar(drawData){
var w = 1060,h = 600;
d3.selectAll("svg").remove();
var svg = d3.select("#chart").append("svg").attr("width",w).attr("height",h);
uni.forEach(function(element,index,array){
$('.uni').css("top",function(index){
return (index + 1) * 18 + 28;
});
});
$(".rankingheader").css("display","block");
$("#switch input").prop("checked", false);
starData = drawData;
revCountData = drawData;
sentData = drawData;
bizCountData = drawData;
drawAxis(drawData);
drawStar(starData);
drawRev(revCountData);
drawSent(sentData);
drawBiz(bizCountData);
drawLineA(starData);
drawLineB(starData,revCountData);
drawLineC(revCountData,sentData);
drawLineD(sentData,bizCountData);
// cart is a list which stored the id selected by user
if(cart.length > 0){
cart.forEach(function(element,index,array){
d3.select("#starHoverLine" + element).attr("visibility","visible");
d3.select("#starHintText" + element).attr("visibility","visible");
d3.select("#revHoverLine" + element).attr("visibility","visible");
d3.select("#revHintText" + element).attr("visibility","visible");
d3.select("#sentHoverLine" + element).attr("visibility","visible");
d3.select("#sentHintText" + element).attr("visibility","visible");
d3.select("#bizHoverLine" + element).attr("visibility","visible");
d3.select("#bizHintText" + element).attr("visibility","visible");
d3.select("#lineA" + element).style("stroke","red");
d3.select("#lineB" + element).style("stroke","red");
d3.select("#lineC" + element).style("stroke","red");
d3.select("#lineD" + element).style("stroke","red");
d3.select("#starBar" + element).attr("fill","red");
d3.select("#revBar" + element).attr("fill","red");
d3.select("#sentBar" + element).attr("fill","red");
d3.select("#bizBar" + element).attr("fill","red");
});
}
}
Your two functions are not called simultaneously; they're called one after another. If it appears that they're being called simultaneously, one of two things is happening:
drawBars is starting something that finishes asynchronously (like an ajax request or an animation), or
drawBars is making changes that aren't shown by the browser immediately and you want to yield back to the browser briefly to allow it to show (render) those changes before calling updateColor.
If it's #1, then you'll need to look at the documentation for the asynchronous operation that drawBars is starting to find out how to know when it finishes. Usually this is a callback or a promise. Depending on which it is, you'll either need to pass updateColors into drawBars as an argument (so you can then call it from the asynchronous callback), or have drawBars return the promise and use the promise's then method to add updateColors to the queue of functions to call when the promise is fulfilled.
If it's #2, that's much simpler:
setTimeout(updateColors, 100); // Wait 100ms (1/10th second) and call `updateColors`

Im trying to find the error in this code, testing my javascript-code

Yo community! might need some insights here.. :) I'm learning some more advance js-concepts. Im running this code but the result is not showing up as I was expecting..I can't see the error...any idea? thanks!
<script type="text/javascript">
(function() {
var results, queue = [];
this.assert = function(pass, msg) {
var type = pass ? "PASS" : "FAIL";
var str = "<li class='" + type + "'><b>" +
type + "</b> " + msg + "</li>";
if ( queue )
queue.push( str );
else
results.innerHTML += str;
};
window.addEventListener("load", function() {
results = document.getElementById("results");
results.innerHTML = queue.join('');
queue = null;
});
// calling assert but it's not showing up the <li> with the message....( why? )
assert( true, "I always pass!" );
})();
</script>
".is there any chance that else-statement will be used? why is the idea of the else-statement?"
The way this assert() function works is that if it is called before the document load event has occurred any results are stored in the queue array: the condition if (queue) will be true because queue refers to the array.
Then when the load handler runs it takes everything already in queue and outputs it to the results element before setting queue to null:
results.innerHTML = queue.join('');
queue = null;
Any calls to assert() after the document load will then find that if (queue) is false because queue is null, so then the else will be executed and any results will be output directly to the results element.
In your code as shown, there is only one call to assert() and it will occur before the document load handler has run.
(Here's a clunky demonstration of this - presses to the button will be after the load event: http://jsfiddle.net/JDFuR/1/)

Javascript Variable Sometimes Undefined

I know this question has been asked several times, but I couldn't seem to find a solution that worked for me in any of the previous questions. I have a variable that gets set when my HTML page is done loading, but sometimes when my code tries to access that variable, it says that it is undefined. I'm not sure why, since I believe I am waiting for everything to load properly. This exception seems to happen randomly, as most of the time all the code runs fine. Here's a simplified version of my code:
var globalVar;
function initStuff(filePath) {
// I wait till the HTML page is fully loaded before doing anything
$(document).ready(function(){
var video = document.getElementById("videoElementID");
// My parseFile() function seems to run smoothly
var arrayOfStuff = parseFile(filePath);
if (arrayOfStuff == null) {
console.error("Unable to properly parse the file.");
} else {
setGlobalVariable(arrayOfStuff);
video.addEventListener("play", updateVideoFrame, false);
}
});
}
function setGlobalVariable(arrayOfStuff) {
window.globalVar = arrayOfStuff;
}
function updateVideoFrame() {
// A bunch of other code happens first
// This is the line that fails occasionally, saying
// "window.globalVar[0].aProperty.anArray[0] is undefined"
var test = window.globalVar[0].aProperty.anArray[0].aProperty;
}
The only thing that I can think of that might be causing this problem is some sort of synchronicity issue. I don't see why that would be the case, though. Help please!
Edit:
In case the asynchronicity issue is coming from my parseFile(xmlFile) method, here is what I'm doing there. I thought it couldn't possibly be causing the issue, since I force the method to happen synchronously, but in case I'm wrong, here it is:
function parseKML(xmlFile) {
var arrayOfStuff = new Array();
// Turn the AJAX asynchronicity off for the following GET command
$.ajaxSetup( { async : false } );
// Open the XML file
$.get(xmlFile, {}, function(xml) {
var doc = $("Document", xml);
// Code for parsing the XML file is here
// arrayOfStuff() gets populated here
});
// Once I'm done processing the XML file, I turn asynchronicity back on, since that is AJAX's default state
$.ajaxSetup( { async : true } );
return arrayOfStuff;
}
The first thing you should do in your code is figure out which part of:
window.globalVar[0].aProperty.anArray[0]
is undefined.
Since you have multiple chained property references and array references, it could be many different places in the chain. I'd suggest either set a breakpoint right before your reference it examine what's in it or use several console.log() statement sto output each nested piece of the structure in order to find out where your problem is.
console.log("globalVar = " + globalVar);
console.log("globalVar[0] = " + globalVar[0]);
console.log("globalVar[0].aProperty = " + globalVar[0].aProperty);
console.log("globalVar[0].aProperty.anArray = " + globalVar[0].aProperty.anArray);
console.log("globalVar[0].aProperty.anArray[0] = " + globalVar[0].aProperty.anArray[0]);
If the problem is that globalVar isn't yet set, then you have a timing problem or an initialization problem.
If the problem is that one of the other properties isn't set, then you aren't initializing globalVar with what you think you are.
You may also want to write your code more defensibly so it fails gracefully if some of your data isn't set properly.
You need to use defensive programming.
http://www.javascriptref.com/pdf/ch23_ed2.pdf
Example:
var video = document.getElementById("videoElementID") || 0;
-
if( video && video.addEventListener ){
video.addEventListener("play", updateVideoFrame, false);
}
Here's another version of your code.
window.globalVar = globalVar || [];
function setGlobalVariable(arrayOfStuff) {
window.globalVar = arrayOfStuff;
}
function updateVideoFrame() {
// A bunch of other code happens first
// This is the line that fails occasionally, saying
// "window.globalVar[0].aProperty.anArray[0] is undefined"
if( window.globalVar ){
var g = window.globalVar || [];
var d = (g[0] || {})["aProperty"];
// etc...
}else{
console.error( "test error." );
}
}
function initStuff(filePath) {
// I wait till the HTML page is fully loaded before doing anything
$(document).ready(function () {
var video = $("#videoElementID");
// My parseFile() function seems to run smoothly
var arrayOfStuff = parseFile(filePath) || [];
if (arrayOfStuff == null || video == null ) {
console.error("Unable to properly parse the file.");
} else {
setGlobalVariable(arrayOfStuff);
video.bind("play", updateVideoFrame);
}
});
}

How to ensure my javascript function only executes after all external javascripts are loaded?

I am developing a WebPart in SharePoint,and I need to draw something in my WebPart using excanvas.js.But sometimes it shows nothing.The error message is:
Object doesn't support property or method 'getContext'
When I debug it,it breaks at here:
var ctxBg = document.getElementById(backgroundId).getContext("2d");
The "backgroundId" is the id of one canvas element.
This error happens not every times,just sometimes,so I think if my js function is executed before the excanvas.js is loaded.I register the excanvas.js with the code:
this.Page.ClientScript.RegisterClientScriptInclude("ExCanvasJs", "wpresources/MyWebPart/js/excanvas.js");
So how to ensure my function is executed after the excanvas.js is loaded?Or I'm wrong at this problem?Would you give me your advice?
my js function:
function DrawMeter(meter, contextCollection) {
var backgroundId = meter.meterbackground;
var pointerId = meter.meterpointer;
var containerId = meter.metercontainer;
if (contextCollection != null && contextCollection.length > 0) {
for (var i = 0; i < contextCollection.length; i++) {
DrawSingleMeter(backgroundId + "_" + i, pointerId + "_" + i, containerId + "_" + i, contextCollection[i]);
}
}
function DrawSingleMeter(backgroundId, pointerId, containerId, context) {
var ctxBg = document.getElementById(backgroundId).getContext("2d");
var ctxPointer = document.getElementById(pointerId).getContext("2d");
drawing...
}
you need to put it into a page ready handler. otherwise at the time the javascript is executed the element might not be available yet.
consider using jquery or another js library for this, if you can't use it here's a link on how to use the native js version of the onload event

Categories

Resources