43

Angular リソースを使用して Twitter に接続する方法を説明しているこのAngularJS チュートリアルを見ていました。(ビデオ チュートリアル) サンプル コントローラーで設定されるリソースは次のとおりです。

$scope.twitter = $resource('http://twitter.com/:action',
    {action: 'search.json', q: 'angularjs', callback: 'JSON_CALLBACK'},
    {get: {method: 'JSONP'}});

このチュートリアルでは、呼び出しを使用してリソースからデータを取得する方法がいくつかあることを示していgetます。最初の方法は、コールバックを get 関数に渡すことです。コールバックは、ajax リクエストが返された後、結果とともに呼び出されます。

$scope.twitter.get(function(result) {
    console.log('This was the result:', result);
});

私はこの方法を理解しています。それは私にとって完全に理にかなっています。リソースは、データを取得できる Web 上の場所を表し、get単純に URL に対して ajax 呼び出しを行い、json を取得し、json でコールバック関数を呼び出します。パラメータはそのresultjsonです。

これが非同期呼び出しであることは明らかなので、私には理にかなっています。つまり、内部では ajax 呼び出しが発生し、呼び出しに続くコードはブロックされずに実行され続けます。その後、不確定な時点で xhr が成功すると、コールバック関数が呼び出されます。

次に、チュートリアルは、はるかに単純に見える別の方法を示していますが、それがどのように機能するかわかりません:

$scope.twitterResult = $scope.twitter.get();

下の xhrgetは非同期である必要があると想定していますが、この行では、get呼び出しの戻り値を、あたかも同期的に返されるかのように変数に割り当てています。

これを理解していないのは間違っていますか?そんなことがあるものか?それが機能するのは本当に素晴らしいことだと思いますが、わかりません。

その下の xhr がオフになって非同期に処理されている間に何かgetを返すことができることは理解していますが、コード例を自分で従うと、後続の行が実行される前に実際の twitter コンテンツを取得することがわかります。たとえば、その行の直後に書き込むと、後で置き換えられる一時的な値ではなく、コンソールに記録された twitter の結果が表示されます。$scope.twitterResultconsole.log($scope.twitterResult)

さらに重要なことは、これが可能であるため、これと同じ機能を利用する Angular サービスを作成するにはどうすればよいでしょうか? ajax リクエスト以外にも、JavaScript で使用できる非同期呼び出しを必要とする他の種類のデータ ストアがあり、このスタイルで同期的にコードを記述できるようになりたいと思っています。たとえば、IndexedDB です。Angular の組み込みリソースがどのように機能しているかを把握できれば、試してみたいと思います。

4

2 に答える 2

63

$resource は同期ではありませんが、この構文は次のように示唆している可能性があります。

$scope.twitterResult = $scope.twitter.get();

ここで何が起こっているかというと、AngularJS への呼び出しは、への呼び出し後、すぐtwitter.get()返され、結果は空の配列になります。次に、非同期呼び出しが終了し、サーバーから実際のデータが到着すると、配列は data で更新されます。AngularJS は、返された配列への参照を単純に保持し、データが利用可能になったときにそれを埋めます。

「魔法」が発生する $resource 実装のフラグメントを次に示します: https://github.com/angular/angular.js/blob/master/src/ngResource/resource.js#L372

これは、$resource ドキュメントにも記載されています。

$resource オブジェクト メソッドを呼び出すと、すぐに空の参照が返されることを認識することが重要です (オブジェクトまたは配列によって異なりますisArray)。サーバーからデータが返されると、既存の参照に実際のデータが取り込まれます。通常、リソースはモデルに割り当てられ、ビューによってレンダリングされるため、これは便利なトリックです。オブジェクトが空の場合、レンダリングは行われません。サーバーからデータが到着すると、オブジェクトにデータが取り込まれ、ビューが自動的に再レン​​ダリングされて新しいデータが表示されます。これは、ほとんどの場合、アクション メソッドのコールバック関数を記述する必要がないことを意味します。

于 2012-08-15T08:56:39.037 に答える
5

$qもこのトリックを行うことができます。次のようなものを使用して、通常のオブジェクトを「遅延値」に変換できます。

var delayedValue = function($scope, deferred, value) {
    setTimeout(function() {
        $scope.$apply(function () {
            deferred.resolve(value);
        });
    }, 1000);
    return deferred.promise;
};

次に、それをコントローラーで使用して、OPの例で$ scope.twitter.get()が実行するのと同様の効果を取得します。

angular.module('someApp', [])
.controller('someController', ['$scope', '$q', function($scope, $q) {
  var deferred = $q.defer();
  $scope.numbers = delayedValue($scope, deferred, ['some', 'numbers']);
}]);
于 2012-12-26T17:23:59.127 に答える