有一个代码:
var theContent;
Windows.Storage.PathIO.readTextAsync(filepath).done(function (fileContent) {
theContent= fileContent;
},
function (error) {
});
然后当我想在Windows.Storage.PathIO.readTextAsync之外使用'theContent'时, 它不起作用...... theContent变量根本不包含任何内容。
代码的哪一部分有误? 谢谢!
我把部分原因造成了麻烦。
global.js ,其中包含用于共享的命名空间数组变量。 (在a.js和b.js中)
WinJS.Namespace.define("GLOBAL", {
theList: null
});
a.js ,会在某个文件中加载文字。
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 以各种方式使用GLOBAL.theList
ready: function (element, options) {
new Windows.UI.Popups.MessageDialog("#2 length " + GLOBAL.theList.length, "MESSAGE").showAsync().then();
},
这是问题所在。 当我调试 a.js 时,我看到 GLOBAL.theList 正确包含文件的文本。但是,当我将页面导航到 b.html(b.js)时,弹出消息显示“#2 length 0”,这意味着 GLOBAL.theList 不包含任何内容。
答案 0 :(得分:3)
您要求theContent
直线(程序)而不是回调的部分。
.done(function (content) { doStuff(content); });
或者,如果doStuff
没有使用this
并且您不需要对其执行任何其他操作,那么只有.done(doStuff);
和doStuff会在内容时触发内容回来了。
loadImage = function () {}; // returns promise
showImage = function (image) {} // shows image
var imageLoading = loadImage("img/huge-img.bmp");
imageLoading.done(showImage);
或者为了使它更清晰,构建showImage
以使用promises(在函数内部订阅它们的回调)。
function showImage(promise) {
promise.done(function (img) {
document.body.appendChild(image);
});
现在你有了
var image = loadImage("huge-img.bmp");
showImage(image);
使用承诺。看起来很自然。
编辑 re:命名空间
你仍然可能不想把事情放到列表中,这是你在回调中做的唯一事情。
什么是使用清单?
theList.push()
是一个自定义函数,与[].push()
具有相同的名称但是会有额外的东西吗?
或者只是一堆东西?
问题在于:
就像AJAX回调一样,承诺不会等待事情完成,然后继续下一件事。
因此,如果你的程序试图对那个数组做一些事情,在done
之外(当数组最终会有数据时),那么这些函数将在一个空数组上工作。
相反,您应该使用方法(回调)来处理Promise的返回。
// these both do the same thing
/* ... */ .done(function (data) { NAMESPACE.module.callback(data); });
/* ... */ .done(NAMESPACE.Module.callback.bind(NAMESPACE.Module));
// if NAMESPACE.Module.callback ***does not use `this`*** you can write
/* ... */ .done(NAMESPACE.Module.callback);
// if you are unsure for even a second, do one of the other two calls
如果您需要对回调中的数据进行更多操作,那么只需执行以下操作:
/* ... */ .done(function (data) {
var arr = doStuff(data);
arr.forEach(function (obj) {
NAMESPACE.Module.list.push(obj);
});
NAMESPACE.Module.callback_relying_on_list();
});
请注意,这里的2个键是:
this
正确无误编辑#2 re:source
看看你在这里做了什么(简化):
// a.js
function getFiles () {
GLOBAL.list = [];
getAsyncData().done(function (text) {
GLOBAL.list.push({ content : text });
});
}
//b.js
GLOBAL.Messages = {
write : function (messages) {
messages.forEach(/* ... */);
},
ready : function () { alert(GLOBAL.list.length); } }
};
// main program
getFiles();
GLOBAL.Messages.ready();
GLOBAL.Messages.write(GLOBAL.list);
我知道这不是你的确切代码,但请看一下这种简化的情况:
如果我的getFiles
功能运行正常但服务器没有将数据发回30秒会怎样?
我的ready
和write
函数不会等待这种情况发生
我的getFiles
完成后就会开火。
所以在这里,你在错误的地方得到了这个承诺 这是100%被称为正确的方式,但为什么不这样做:
// a.js
function getFiles () {
var filesLoaded = getAsyncData(); // I'm collecting the promise, not chaining it.
// again, simplified
filesLoaded.done(function (text) { GLOBAL.list.push({ content : text}); });
// ***super important part***
return filesLoaded;
}
// b.js
/* ... */ = {
ready : function (promise) {
promise.done(function () { alert(GLOBAL.list.length); });
},
write : function (promise) {
promise.done(/* write the list */);
}
}
现在你的主要看起来像这样:
var files = getFiles(); // files is the promise
// files.done, files.then, etc
GLOBAL.Messages.ready(files); // giving the promise to the method
// ready(promise) will subscribe to promise.done
GLOBAL.messages.write(files); // so will write(promise);
以这种方式处理promises时,请记住files
我的示例与您在链中添加.done()
的完全相同的对象。
还要记住,有时你的函数会关心promise返回的值,有时候,函数只是想知道什么时候完成了promise,所以他们可以做一些事后需要发生的事情,而不是设置定时器检查。
使用已清理的功能,只要您处理同步数据就可以接受承诺,现在您拥有:
var files = readTextFromFiles();
/* ... */.ready(promise);
这是否意味着你还需要一个功能来处理这个ready
正在做的事情以及旧的准备状态?
嗯,是的......
但是值得知道你的功能不会提前熄灭 它看起来很干净,没有巢,同时仍然100%同步。
如果您匆忙,或者您无法编辑其他功能,那么您可能会做出错误的想法,这可能是在页面底部引导内容:
(function (promise) { promise.done(function () {
/* ... everything() ... */ });
}(files));
丑陋且难以挑选,需要在单独的页面上进行编辑,但至少它仍然是异步的,它仍然按顺序进行。
但 仍然 意味着返回并收集并传递承诺。
希望有所帮助。