12

私は、JQuery 互換の promise を使用して Parse を参照したことがあることに懸念を抱いています。jQueryの promise を使用すると、消費者が promise の状態を変更できることを読んだことがあります。Promises/A+に準拠していることが知られている別の promise 実装( ECMAScript 6 実装、またはBluebirdなど) を Parse JavaScript SDK で使用することは可能ですか?

通常、これは不可能だと思いますが、Parse JavaScript SDK の v1.4.2 では、Parse.Promise の実装でプロパティ「_isPromisesAPlusCompliant」が false として定義され、ライブラリ内のさまざまな関数でチェックされます。

注: この質問は、もともとParse Developers groupで行われましたが、回答がありませんでした。

4

3 に答える 3

5

ネイティブの Promise または適切なポリフィルを使用できます。次のように、Promise.resolve 呼び出しで任意の thenable (パブリック then メソッドを持つ Promise のようなオブジェクト) をカプセル化できます。

var promise = Promise.resolve($.getJSON("/something.json"));

これにも then メソッドがありますが、頭痛の種はありません。それはまだ動作するはずです。

于 2015-06-28T11:43:42.673 に答える
5

私は、Parse が jQuery 互換の promise を使用していることを懸念しています。jQuery の promise では、消費者が promise の状態を変更できると読んだことがあります。

気にする必要はありません。「jQuery互換」は多くのことを意味する可能性があり、Parse promiseは消費者が状態を変更することを確かに許可していません1 (jQueryは何年も前から変更を行っていないため)。ところで、それらはA +「互換性」もあります:-)

1: public メソッドを使用。つまり、他のほとんどの実装よりも多くはありません。

Parse JavaScript SDK で Promises/A+ に準拠していることが知られている別の promise 実装を使用することは可能ですか?

はい。Parse SDK は有効な A+ thenablesthenを返します。つまり、お気に入りの promise 実装のコールバックから Parse promise を返すことができ、問題なく動作することが期待できます。

myCompliantPromise.then(function(res) {
    return parse_query.get(…);
}).then(…)

を使用して、実装の有効な promise にそれらをキャストすることもできます。Promise.resolve次に例を示します。

Promise.resolve(parse_query.get(…)).then(…);

通常、これは不可能だと思いますが、Parse JavaScript SDK の v1.4.2 では、Parse.Promise の実装でプロパティが定義さ_isPromisesAPlusCompliantfalse、ライブラリ内のさまざまな関数でチェックされます。

彼!残念ながら文書化されていませんが、このフラグを使用すると、実際にネイティブの Parse.com promise ライブラリをアプリで A+ 準拠にすることができます

Parse.Promise._isPromisesAPlusCompliant = true;

更新: 新しいバージョンでは、これは下線付きのプロパティとして公開されていませんが、(文書化されていない)Parse.Promise.enableAPlusCompliant()メソッドを呼び出す必要があります。詳細については、問題 #57を参照してください。

コードを確認しましたが、このフラグは基本的に次の 3 つの点を変更します。

  • コールバックの例外thenがキャッチされ、グローバル エラーではなく、結果の promise が拒否されます。だからあなたはthrowそれらで使うことができます。
  • returnコールバックからの値onRejected( の 2 番目のパラメーター) の場合then、エラーは処理されるはずであり、結果の promise は拒否される代わりに実行されます。
  • すべてのthenコールバックは非同期で実行されます。

これらは実際、現時点での jQuery実装に固有の問題を正確に解決しています。Deferred

trueParse は、この設定を黙って移行してデフォルトにすることを計画しており、ユーザーにとって何か問題があるかどうかをテストしていると仮定します。まだ文書化されていなくても、かなり安全に使用できると思います。

すべての Parse API がカスタム ライブラリの promise を返すようにしたいと考えています。

それは可能ですが、それほど単純ではありません。基本的に 2 つのアプローチがあります。

  • API 内のすべての promise を返すメソッドを で構成することによって装飾しますPromise.resolve。これは基本的に @dancamper が提案したものです
  • Parse.Promiseライブラリのラッパーで上書きします。

2 つ目は、より効率的で安定しているように見えます。Parse が API を変更するときに微調整する必要がないため、保守が容易です。

Parse.Promise = (function(oldPromise, Promise) {
    function promise() {
        var res, rej;
        var p = new Promise(function(_res, _rej) {
            res = _res;
            rej = _rej;
        });
        p.resolve = res;
        p.reject = rej;
        return p;
    }
    promise.is = oldPromise.is;
    promise.as = Promise.resolve;
    promise.error = Promise.reject;
    promise.when = Promise.all; // ²
    promise._continueWhile = oldPromise._continueWhile;
    Promise.prototype._continueWith = oldPromise.prototype._continueWith;
    Promise.prototype._thenRunCallback = oldPromise.prototype._thenRunCallback;

    // you might not need / want these ³
    Promise.prototype.always = oldPromise.prototype.always;
    Promise.prototype.done = oldPromise.prototype.done; 
    Promise.prototype.fail = oldPromise.prototype.fail;

    return promise;
}(Parse.Promise, require("Bluebird"))); // or whatever

2:Promise.all配列にParse.Promise.when解決されますが、複数の引数で解決されます (以下を参照)。promise.when = oldPromise.when;これを保存して代わりに使用する必要がある場合があります。
3: ここでカスタム ライブラリのメソッドを上書きしないように注意してください。Parse はこれらのメソッドを必要としません。jQuery との互換性のためです。

Parse は、jQuery のように、promise を複数の値で解決する場合があることに注意してくださいParse._ajax。内部的にはこの機能に依存していませんが、お気に入りの Promise ライブラリがそれらにどのように対処しているかを確認する必要があります。

于 2015-07-04T17:11:49.653 に答える
3

1 つのオプションは、Parse SDK プロトタイプを変更して、異なるタイプの Promise を返すことです。

良い出発点は、このライブラリhttps://github.com/brandid/parse-angular-patch/blob/master/src/parse-angular.jsです。これは、Parse プロトタイプにパッチを適用して、AngularJS の約束を返します。

            // Keep a handy local reference
            var Parse = $window.Parse;

            //-------------------------------------
            // Structured object of what we need to update
            //-------------------------------------

            var methodsToUpdate = {
                "Object": {
                    prototype: ['save', 'fetch', 'destroy'],
                    static: ['saveAll', 'destroyAll']
                },
                "Collection": {
                    prototype: ['fetch'],
                    static: []
                },
                "Query": {
                    prototype: ['find', 'first', 'count', 'get'],
                    static: []
                },
                "Cloud": {
                    prototype: [],
                    static: ['run']
                },
                "User": {
                    prototype: ['signUp'],
                    static: ['requestPasswordReset', 'logIn']
                },
                "FacebookUtils": {
                    prototype: [],
                    static: ['logIn', 'link', 'unlink']
                },
                "Config": {
                    prototype: [],
                    static: ['get']
                }
            };

            //// Let's loop over Parse objects
            for (var k in methodsToUpdate) {

                var currentClass = k;
                var currentObject = methodsToUpdate[k];

                var currentProtoMethods = currentObject.prototype;
                var currentStaticMethods = currentObject.static;


                /// Patching prototypes
                currentProtoMethods.forEach(function(method){

                    var origMethod = Parse[currentClass].prototype[method];

                    // Overwrite original function by wrapping it with $q
                    Parse[currentClass].prototype[method] = function() {

                        return origMethod.apply(this, arguments)
                        .then(function(data){
                            var defer = $q.defer();
                            defer.resolve(data);
                            return defer.promise;
                        }, function(err){
                            var defer = $q.defer();
                            defer.reject(err);
                            return defer.promise;
                        });


                    };

                });


                ///Patching static methods too
                currentStaticMethods.forEach(function(method){

                    var origMethod = Parse[currentClass][method];

                    // Overwrite original function by wrapping it with $q
                    Parse[currentClass][method] = function() {

                        return origMethod.apply(this, arguments)
                        .then(function(data){
                            var defer = $q.defer();
                            defer.resolve(data);
                            return defer.promise;
                        }, function(err){
                            var defer = $q.defer();
                            defer.reject(err);
                            return defer.promise;
                        });

                    };

                });


            }
于 2015-07-02T09:41:04.747 に答える