2017-01-23 13 views
2

楽しい/勉強のために私はPromiseを拡張したいと思っていましたが、標準的な古い構文ではできないという、信じられないほど知名度の高い人たちがstackoverflowで見つけました。しかし私はとにかく欲しかったので、Promiseオブジェクトを作成し、他の人が古いES6以外の構文を使用して継承できるようにする独自のIPromiseクラスを作成することを考えました。これは継承可能な約束ですか?

私は、この実装が組み込みPromiseが直接継承可能な宇宙とどのように違うのか知りたいです。誰かが洞察力を持っている場合、組み込みPromiseの実装者は古い構文で継承を許可しません。

// Inheritable Promise 
IPromise = function(executor) { 
    this.promise = new Promise(executor); 
}; 
IPromise.prototype = Object.create(Promise.prototype); 
IPromise.prototype.constructor = IPromise; 
IPromise.prototype.catch = function(fail) { 
    return this.promise.catch(fail); 
} 
IPromise.prototype.then = function(success, fail) { 
    return this.promise.then(success, fail); 
}; 

// Usage 
// No different to builtin Promsise 
(new IPromise(function(resolve, reject) { return resolve(true); })) 
    .then(function(response) { 
     console.log('IPromise then is like Promise then', response); 
    }) 
    .catch(function(error) { 
     console.log('IPromise catch is like Promise catch', error); 
    }); 

はここですべての要求にかかわらず、それらのいずれかが失敗するかどうかを完了するのを待って、バッチAJAXのためにそれを拡張する例を示します

は、ここに私の拡張/継承IPromiseクラスです。組み込み機能とは少し異なります。

// Inheriting 
// You can inherit from IPromise like you would any normal class. 
BatchAjax = function(queries) { 
    var batchAjax = this; 
    this.queries = queries; 
    this.responses = []; 
    this.errorCount = 0; 
    IPromise.call(this, function(resolve, reject) { 
     batchAjax.executor(resolve, reject); 
    }); 
}; 
BatchAjax.prototype = Object.create(IPromise.prototype); 
BatchAjax.prototype.constructor = BatchAjax; 
BatchAjax.prototype.executor = function(resolve, reject) { 
    var batchAjax = this; 
    $.each(this.queries, function(index) { 
     var query = this; 
     query.success = function (result) { 
      batchAjax.processResult(result, index, resolve, reject); 
     }; 
     query.error = function (jqXhr, textStatus, errorThrown) { 
      batchAjax.errorCount++; 
      var result = { 
       jqXhr: jqXhr, textStatus: textStatus, errorThrown: errorThrown 
      }; 
      batchAjax.processResult(result, index, resolve, reject); 
     }; 
     $.ajax(query); 
    }); 
}; 
BatchAjax.prototype.processResult = function(result, index, resolve, reject) { 
    this.responses[index] = result; 
    if (this.responses.length === this.queries.length) { 
     if (this.errorCount === 0) { 
      resolve(this.responses); 
     } else { 
      reject(this.responses); 
     } 
    } 
}; 

// Usage 
// Inheriting from IPromise is boring, which is good. 
var baseUrl = 'https://jsonplaceholder.typicode.com'; 
(new BatchAjax([{url: baseUrl + '/todos/4'}, {url: baseUrl + '/todos/5'}])) 
    .then(function(response) {console.log('Yay! ', response);}) 
    .catch(function(error) {console.log('Aww! ', error);}); 

私はちょうど学んでいるが、これは有用ではなく、面白​​いことを心に留めておいてください。しかし、残酷な批判をお寄せください、私はこれが愚かなことであるという考えに公開しています:)

すべてのコードを見て、ごめんなさい!

編集:元々私が約束を延長しようとしていたところです:Extending a Promise in javascript。 PromiseコンストラクタはPromise(私が思う)ではないものを初期化していることに気づいたら、Typeエラーをスローするため、古い構文では動作しないようです。

edit2:jfriend00さんのコメントは興味深いものです。どのようなIPromise.then戻す必要がありますか?現時点ではそれは単なる約束ですが、それはIPromiseであるべきですか?

IPromise.prototype.then = function(success, fail) { 
    this.promise.then(success, fail); 
    return new IPromise(whatGoesHere?); 
}; 

または、それから継承したクラスのインスタンス。

IPromise.prototype.then = function(success, fail) { 
    this.promise.then(success, fail); 
    return new this.constructor(whatGoesHere?); 
}; 

これを返すだけでよいですか?

IPromise.prototype.then = function(success, fail) { 
    this.promise.then(success, fail); 
    return this; 
}; 

私はPromise.thenがPromiseを返すと知っていますが、Promiseがセットアップされているか、動作するとは思われません。だからこそ私はこの問題を避け、プロミスをこれから返送しました。他の賢明な解決法はありますか?

+3

"これは標準の古い構文ではできません" – tommybananas

+2

あなたはあなたができなかったと言われた質問にリンクすることもできます。いくつかのプログラミング言語では、 "I"接頭辞は具体的なクラスではなくインタフェースを示すために使用されています。その質問の命名は、一見、それらの人々のために混乱するかもしれません。 –

+1

@tommybananasそれは母国語のタイプなので、 '__proto__'を使ってハックせずに' Array'や 'Error'を拡張できないように、' class'構文(ES5はない)で拡張することしかできません。 – loganfsmyth

答えて

2

はい、お客様のIPromiseは、実際にはPromiseのように動作します。しかし、たとえば、あなたはそれらのネイティブの約束のメソッドを呼び出すことはできません。

var p = new Promise(function(resolve) { return resolve(true); }); 
var ip = new IPromise(function(resolve) { return resolve(true); }); 
Promise.prototype.then.call(p, v => console.log(v)); 
Promise.prototype.then.call(ip, v => console.log(v)); // TypeError 

あなたのIPromiseインスタンスが本当の約束になりたい場合は、彼らはPromiseで初期化する必要があります。そのコンストラクタは、あなたがエミュレートできない[[PromiseState]]のようないくつかの内部スロットを追加します。しかし、Promiseによって作成された約束はPromise.prototypeから継承され、ES6の前には、オブジェクトが作成された後で[[Prototype]]をIPromise.prototypeに変更する標準的な方法はありません。 ES6クラス、

class IPromise extends Promise { 
    // You can add your own methods here 
} 
0

、以下のものを使用して

はjfriend00のコメントで示唆されました。あなたがIPromisesをチェーンするとき、あなたのIPromise.prototype.then()がちょうどreturn this.promise.then(success, fail);

ミーと通常の約束を返すため

、あなたは、連鎖した後IPromiseオブジェクトを取得することはありません。IPromise.thenだけで実行する必要があります。

this.promise.then(success, fail); 

そして、これらの1つ?

return new IPromise(whatGoesHere?); 
return new this.constructor(whatGoesHere?); 
return this; 

これは約束を拡張することは本当に厄介だ理由の一つです。インフラストラクチャ自体はすべての.then()呼び出しで新しい約束事を作成し、基盤となるインフラストラクチャがサブクラス化をサポートすることなく、インフラストラクチャに取り入れる簡単な方法を提供しません。 hereのように見える場合は、サポートがある環境にあります。しかし、私はいつも私が他の方法で自分の問題を解決できることを発見しました。だから、私は自分のサブクラスをハックしようとするつもりはないので、それに穴があるようです。

もう一度私に話してください(tobuslieven)。私はこれに同意しますが、私はまだこのクラスを念頭に置いて、機会があればそれを使用するつもりです。私はIPromiseの代わりにPromiseを返すことが可能だと思うし、これを約束することができるのは本当に面白い。

私の答えははい、おそらく十分であり、価値のあるものを実際のどこかで使用する価値があります。

関連する問題