2

このコードを「意図したとおりに」機能させるには、どのようなルートを取るべきか疑問に思っています。API呼び出しは非同期であるため、コンストラクターはデータが読み込まれる前に戻ります。

addSongById: function (songId) {
    var song = new Song(songId);
    console.log(song);
    this.addSong(song);

    if (this.songCount() == 1)
        this.play();

    UserInterface.refresh();
    SongGrid.reload();
},

function Song(songId) {
    $.getJSON('http://gdata.youtube.com/feeds/api/videos/' + songId + '?v=2&alt=json-in-script&callback=?', function (data) {
        this.id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); });
        this.songId = songId;
        this.url = "http://youtu.be/" + songId;
        this.name = data.entry.title.$t;
    });
}

コンストラクターが時期尚早に戻らないように強制することは可能ですか?理想的には、Songコンストラクターに任意の量のパラメーターを渡して、Songにのみ関連する情報をその範囲外に持ち込む必要はありません。

4

4 に答える 4

7

ほとんどの非同期操作と同様にDeferred、この状況ではaを使用します。JSのコンストラクターは、自分自身のインスタンスを返す義務はありません。

function Song(songId) {
    var song = this;
    var def = new $.Deferred();
    $.getJSON('http://gdata.youtube.com/feeds/api/videos/' + songId + '?v=2&alt=json-in-script&callback=?', function (data) {
        song.id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); });
        song.songId = songId;
        song.url = "http://youtu.be/" + songId;
        song.name = data.entry.title.$t;
        def.resolve(song);
    });
    return def.promise();
}

var promise = new Song(songId);
promise.done(function(instance) {
    // you've got a Song instance
});
于 2012-06-06T06:58:27.507 に答える
3

オプション$.ajaxの代わりに使用することをお勧めします。ただし、これにより、他のすべてのJavaScriptの実行がロックされます。また、たとえばサーバーが何らかの理由で応答しない場合、これは問題になる可能性があります。$.getasync: false

したがって、これは悪い習慣です。たとえば、コールバックを使用します

function Song(songId, callback) {
    var self = this;
    $.getJSON('http://gdata.youtube.com/feeds/api/videos/' + songId + '?v=2&alt=json-in-script&callback=?', function (data) {
        self.id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); });
        self.songId = songId;
        self.url = "http://youtu.be/" + songId;
        self.name = data.entry.title.$t;
        callback();
    });
}

var song = new Song(songId, function() {
    // The other code goes here.
});
于 2012-06-06T06:42:00.290 に答える
3

...それは悪い習慣です。コンストラクターは、そのクラスのインスタンスを返す必要があります。それ以外は何も返しません。そうしないと、新しい演算子と継承が台無しになります。

さらに、コンストラクターは新しいインスタンスのみを作成して初期化する必要があります。データ構造とすべてのインスタンス固有のプロパティを設定する必要がありますが、タスクは実行しないでください。可能であれば副作用のない純粋関数であり、すべての利点があります。

参照:コンストラクター関数にPromiseを返すようにするのは悪い習慣ですか?

于 2015-04-25T00:11:31.643 に答える
0

同期呼び出しにより、ブラウザが応答を停止したり、一部のブラウザでスクリプトが強制的に強制終了されたりする場合があります。

Jqueryには、URIへのリクエストを行う際のオプションがあります

asyncBooleanデフォルト:true

デフォルトでは、すべてのリクエストは非同期で送信されます(つまり、これはデフォルトでtrueに設定されています)。同期リクエストが必要な場合は、このオプションをfalseに設定してください。クロスドメインリクエストとdataType:「jsonp」リクエストは同期操作をサポートしていません。同期リクエストはブラウザを一時的にロックし、リクエストがアクティブな間はアクションを無効にする可能性があることに注意してください。jQuery 1.8以降、async:falseの使用は非推奨になりました。

http://api.jquery.com/jQuery.ajax/

これがお役に立てば幸いです

よろしく。

于 2012-06-06T06:41:22.610 に答える