WinJS Promise then 出现错误

3
经过一些实验,我最终得到了以下代码,试图复制C#的await功能:
var promise = new WinJS.Promise(MyFunc())
    .then(function () {
        // Second function which uses data set-up in the first
        MyFunc2();
    });

'MyFunc()'可以正常运行,但'MyFunc2()'却无法执行,导致程序崩溃。我对Promise对象的理解有何误解?

(这是在使用Windows 8操作系统时发生的)

编辑:

现在,'MyFunc()'的完整代码如下:

function MyFunc() {
    var foldername = "Folder";
    var filename = "readme.xml";

    var promise = Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync(foldername).then(function (folder) {
        folder.getFileAsync(filename).then(function (file) {
            var loadSettings = new Windows.Data.Xml.Dom.XmlLoadSettings;
            loadSettings.prohibitDtd = false;
            loadSettings.resolveExternals = false;
            Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file, loadSettings).then(function (doc) {
                dataText = doc.getXml();
                xmlDoc = doc;
            }, function (error) {
                output.value = "Error: Unable to load XML file";
                output.style.color = "red";
            }, function (error) {
                output.value = "Error: Unable to load XML file";
                output.style.color = "red";
            })
        })
    });

    return promise;
};

现在的结果是'MyFunc2()'在'MyFunc()'完成之前执行。'MyFunc2()'使用全局变量xmlDoc,此时该变量未定义。

MyFunc实际上是否返回您需要的数据?还是仅设置一些全局变量,需要在后续函数中使用? - Paul O.
只是设置一些全局变量。 - Paul Michaels
可能是重复问题:等待promise和嵌套的then全部完成 - Raymond Chen
new WinJS.Promise 的参数不是一个 Promise,而是一个 Promise 生成器。由于您已经有了一个 Promise,请直接使用它。var promise = MyFunc().then(...) - Raymond Chen
我不明白为什么这不是我已经在做的事情。 - Paul Michaels
2个回答

3
你应该将所有的Promise串联在一起,然后等待最终Promise的返回。
function MyFunc() {
    var promise = Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync(foldername).then(function (folder) {
        return folder.getFileAsync(filename);
        }).done(function (file) {
            var loadSettings = new Windows.Data.Xml.Dom.XmlLoadSettings;
            loadSettings.prohibitDtd = false;
            loadSettings.resolveExternals = false;
            return Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file, loadSettings);
        }).then(function (doc) {
            dataText = doc.getXml();
            xmlDoc = doc;
            return doc; // whatever the result is
        }, function (error) {
            output.value = "Error: Unable to load XML file";
            output.style.color = "red";
        });
    return promise;
}

你可以链式调用MyFunc返回的Promise:

var promise = MyFunc().then(function(doc) { MyFunc2(...); });

我已经编辑了我的帖子,展示了完整的代码,就像现在这样,尽管这仍然不起作用。 - Paul Michaels
1
已经排好序了。你的建议确实起作用了,但是你把“完成”和“反转”顺序搞反了。 - Paul Michaels

1
好的,根据修改,您将需要采用略微不同的方法。您需要使MyFunc()实际返回您正在创建的promise变量。这将允许您将MyFunc链接到MyFunc2。因此,您可以像这样做:
var promise = Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync(foldername).then(function (folder) {
        folder.getFileAsync(filename).done(function (file) {
            var loadSettings = new Windows.Data.Xml.Dom.XmlLoadSettings;
            loadSettings.prohibitDtd = false;
            loadSettings.resolveExternals = false;
            Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file, loadSettings).then(function (doc) {
                dataText = doc.getXml();
                xmlDoc = doc;
            }, function (error) {
                output.value = "Error: Unable to load XML file";
                output.style.color = "red";
            });
...
return promise;

假设这是 MyFunc() 中唯一的承诺。如果不是,您可以将所有承诺链接在一起,或将它们全部放入数组中并返回,例如 WinJS.Promise.join(promiseArray)

现在您从 MyFunc() 返回一个承诺,您可以使用 then 进行链式调用。

var promise = MyFunc().then(function () {
    // Second function which uses data set-up in the first
    MyFunc2();
});

如果 MyFunc2 同样包含异步代码,您也可以返回这些 promise,并保持链式调用,只要您需要的时间足够长。
var promise = MyFunc().then(function () {
    // Second function which uses data set-up in the first
    return MyFunc2();
}).then(function () {
    //And on and on...
});

最新编辑:MyFunc()确实包含异步代码。你提出的两种方法都可以防止它崩溃,但第二个函数在第一个完成之前就开始执行了。 - Paul Michaels
好的,根据新的信息,我已经修改了我的答案。 - Paul O.
这仍然不起作用。尽管在MyFunc()中它没有,但是在MyFuncs2()的代码在它完成之前执行。 - Paul Michaels

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接