2

現在、Windows 8/WinRT アプリケーションで読み取ったファイルに問題があります。シンプルなナビゲーション スタイルのアプリがあり、複数のページが同じデータにアクセスでき、多数のメンバーを持つ名前空間 (データ) を定義する data.js ファイルがあります。アプリケーションの一部は、アイテムをアプリケーションのローカル データ フォルダーに保存されている txt ファイルに保存します。しかし、他のいくつかのページでは、これを読み込むか、以前に保存されたアイテムのリスト内にアイテムが存在するかどうかを確認する必要があります。これを行うために、data.js ファイルに別のメソッドを追加しました。問題は、アイテムの存在を確認するためにこのメソッドを呼び出すと、非同期の性質のためにすぐに値が返されないことですが、ページ固有の js ファイル内の残りのコードは、その前にまだ実行されているようです。解析に戻ります。これは、アイテムをチェックするロジックが「うまくいかないようです。.done または .then の使用にかかっていると感じていますが、コードは次のとおりです。

  DATA.JS
   var doesItemExist= function(item_id){

    var appFolder = Windows.Storage.ApplicationData.current.localFolder;
   //note I've tried this with and without the first "return" statement
   return  appFolder.getFileAsync(dataFile).then(function (file) {
        Windows.Storage.FileIO.readTextAsync(file).done(function (text) {
            try {
                var json = JSON.parse(text);
                if (json) {
                    for (var i = 0; i < json.items.length; i++) {
                        var temp_item = json.items[i];
                        if (temp_item.id === item_id) {
                            return true;
                            break;
                        }
                    }
                } else {
                    return false;
                }
            } catch (e) {
                return false;
                console.log(e);
            }
        }, function (e) { return false;console.log(e); });
    }, function (e) { // error handling
        return false;
        console.log(e);

    });
}
 WinJS.Namespace.define("Data", {
    doesItemExist: doesItemExist
}); //all of the above is wrapped in a self executing function

次に、Page.js には次のようなものがあります。

    var add = document.getElementById('add');
        if (Data.doesItemExist(selected_item.id)) {
            add.style.display = 'block';
        } else {
            add.style.display = 'none';
        }

ここのすべての変数が割り当てられ、デバッグでエラーが発生することはありません。制御は、getFileAsync にヒットした後、for ループを通過する前に、if/else ステートメントに戻るように見えます。ただし、その後 for ループに入りますが、if ステートメントが終了した後です。これはすべての非同期の性質によるものだと思いますが、それを回避する方法がわかりません。何か案は?

ありがとう

4

1 に答える 1

3

Promise はここで機能するはずです。

新しいナビゲーション アプリを作成し、次のコードを含む Data.js ファイルを追加しました。

(function () {
    var appData = Windows.Storage.ApplicationData;

    function doesItemExist(item_id) {
        return new WinJS.Promise(
            function (completed, error, progress) {
                var exists = false;
                appData.current.localFolder.createFileAsync("data.txt", Windows.Storage.CreationCollisionOption.openIfExists).then(
                    function (file) {
                        Windows.Storage.FileIO.readTextAsync(file).then(
                            function (fileContents) {
                                if (fileContents) {
                                    if (fileContents = "foo!") {
                                        completed(true);
                                    }
                                    else {
                                        completed(false);
                                    }
                                }
                                else {
                                    completed(false);
                                }
                            }
                        );
                    },
                    function (e) {
                        error(e);
                    }
                );
            }
        );
    }

    WinJS.Namespace.define("Data", {
        doesItemExist: doesItemExist
    });
})();

ファイルを取得して解析するためのコードを単純化したことに注意してください。これは、問題とはあまり関係がないためです。重要な部分は、アイテムが存在するかどうかを判断したら、返す Promise の .then または .done をトリガーする completed(exists)を呼び出すことです。createFileAsync の呼び出しから例外が発生した場合と同様に、例外が発生した場合は error(e) を呼び出すことに注意してください (ファイルを作成できるようにする場合は、getFileAsync ではなくこの呼び出しを使用します)存在しないか、存在する場合は openIfExists オプションを使用して既存のファイルを返します)。

次に、Home.js で、ready ハンドラーに次のコードを追加しました。

var itemExists;

var itemExistsPromise = Data.doesItemExist(42);
itemExistsPromise = itemExistsPromise.then(function (exists) {
    itemExists = exists;
    var content = document.getElementById("content");
    content.innerText = "ItemExists is " + itemExists;
});

itemExistsPromise.done(function () {
    var a = 42;
});

var b = 0;

上記のコードは、変数 itemExistsPromise を Data.js の関数から返された promise に設定し、Promise の .then 関数で匿名関数を使用して、変数 itemExists を dosItemExist Promise から返されたブール値に設定し、グラブします。 Home.htmlの<p>タグ (コードから取得できるように id を追加しました) を取得し、アイテムが存在するかどうかを示すテキストを設定します)。.done ではなく .then を呼び出しているため、呼び出しは別の promise を返し、それが itemExistsPromise 変数に渡されます。

次に、itemExistsPromise.done を呼び出して、その上の .then で実行された作業が完了するまで待機する必要がある作業を実行します。

「var a = 42」および「var b = 0」(ブレークポイントを設定する目的でのみ含まれる) 行と「itemExists = exists」行にブレークポイントを設定すると、次のようになることがわかります。さまざまな部分が実行されるときに必要な制御。

それが役立つことを願っています!

于 2012-08-14T15:59:19.330 に答える