there is a code:
var theContent;
Windows.Storage.PathIO.readTextAsync(filepath).done(function (fileContent) {
theContent= fileContent;
},
function (error) {
});
then when I want to use ‘theContent’ outside Windows.Storage.PathIO.readTextAsync,
it doesn’t work… theContent variable contains nothing at all.
What part of the code is wrong?
Thanks!
I put some part of the source which makes trouble.
global.js which contains namespace array variable for sharing. (in a.js and b.js)
WinJS.Namespace.define("GLOBAL", {
theList: null
});
a.js which loads text in a certain file.
function readTextFromFiles() {
GLOBAL.theList= new WinJS.Binding.List();
for (var i = 0; i < theFileList.length; i++) {
if (theFileList.getAt(i).filepath !== null) {
Windows.Storage.PathIO.readTextAsync(theFileList.getAt(i).filepath).done(function (fileContent) {
var splitted = fileContent.split("\r\n");
for (var j = 0; j < splitted.length; j ++) {
GLOBAL.theList.push({
partA: splitted[j]
});
}
},
function (error) {
});
}
}
}
b.js which uses GLOBAL.theList in various ways
ready: function (element, options) {
new Windows.UI.Popups.MessageDialog("#2 length " + GLOBAL.theList.length, "MESSAGE").showAsync().then();
},
Here is the problem.
When I debug a.js, I see that GLOBAL.theList contains text of the file correctly. However, when I navigate the page to b.html(b.js), the popup message shows “#2 length 0” which means that GLOBAL.theList contains nothing.
- I included global.js in the default.html before the page loads other .js files.
- I tested and it worked when I did not use the Windows.Storage.PathIO…. promise. (when I directly put data into the GLOBAL.theList arbitrarily)
The part where you’re asking for
theContentin a straight line (procedural), rather than as a callback..done(function (content) { doStuff(content); });Or, if
doStuffdoesn’t usethisand you don’t need to do anything else with it, just.done(doStuff);and doStuff will be fired with the content when the content comes back.Or to make it even cleaner, build
showImageto use promises (subscribing to their callbacks inside of the function).Now you’ve got
Uses promises. Looks totally natural.
EDIT re: namespacing
You’re still probably not going to want to push things into a list as the only thing you do inside the callback.
What is using the list?
Is
theList.push()a custom function which has the same name as[].push()but does extra stuff?Or is it just an array of stuff?
Here’s the problem:
Like AJAX callbacks, a promise doesn’t wait for the thing to finish, before moving on to the next thing.
So if your program is trying to do something with that array, outside of the
done(when the array will eventually have data), then those functions are going to be working on an empty array.Instead, you should be using methods (callbacks) to handle the Promise’s return.
If you need to do more stuff with the data in the callback, then just do something like:
Notice that the 2 keys here are:
thisis correct in your callbacksEDIT #2 re: source
Have a look at what you’re doing here (simplified):
I know this isn’t your exact code, but look at that simplified situation for a minute:
What happens if my
getFilesfunction works perfectly, but the server doesn’t send my data back for 30 seconds?My
readyandwritefunctions aren’t going to wait for that to happen.They’re going to fire as soon as my
getFilesis done.So here, you’ve got that promise in the wrong spot.
It’s 100% called the right way, but why not do this:
Now your main looks like this:
When working with promises in this way, remember that
filesn my example is the exact same object that you were adding.done()to in your chain.Also remember that sometimes your functions are going to care about the values the promise returns, and other times, the functions just want to know when the promise is done, so they can do something which needs to happen afterwards, instead of setting timers to check.
And with cleaned up functions which take promises any time you’re dealing with a sync data, now you have:
Does it mean that you need one more function to sit between what this
readyis doing and what your old ready looks like?Well, yeah…
But is it worth it to know that your functions aren’t going to go off early.
And it looks really clean, without the nests, while still being 100% a sync.
If you’re in a rush, or you can’t edit those other functions, you could do the bad idea, which would be to bootstrap stuff at the bottom of the page:
Ugly and hard to pick apart and needs to be edited on separate pages, but at least it’s still async and it’s still doing things in order.
But it still means returning and collecting and passing the promise around.
Hope that helps.