2017-08-28 16 views
0

を解決するとobject.thenトリガ私はデシベルメソッドを含むクラスを持っており、それはプロパティへのアクセスを処理するプロキシに包まれています。問題は、ここでの約束に関連しているので、同じ問題を再現された単純化されたサンプルコードです:約束は

const handler = { 
    ownKeys(target) { 
    return Object.keys(target._attributes) 
    }, 
    get(target, property) { 
    console.log(`<-${property}`) // <-- this logs what properties are being accessed 
    if (typeof target[property] !== 'undefined') { 
     return Reflect.get(target, property) 
    } 
    return Reflect.get(target._attributes, property) 
    }, 
    set(target, property, value) { 
    target._attributes[property] = value 
    return true 
    } 
} 
class User { 
    static table = 'users' 
    static fetch(query = {}, opts = {}) { 
     return new Promise((resolve, reject) => { 
      setTimeout(() => { 
      resolve(new this(query)) 
      }, 500) 
     }) 
    } 
    constructor(attributes = {}) { 
     this._attributes = attributes 
     return new Proxy(this, handler) 
    } 
} 
async function trigger() { 
    const user = await User.fetch({test:'test'}) 
    console.log(JSON.stringify(user._attributes)) 
} 
trigger() 

すべては、私は、このようなを使用してのパフォーマンスヒットを決定するためにプロキシにプリントアウトを追加したテスト中に、うまく機能私のモデルが有望なチェーンの中から呼び出されることに気付きました。

出力例は次のとおりです。

<-then 
<-_attributes 
{"test":"test"} 

私はnew this(query)を返すことは約束は多分それは約束返されると、その結果.then()が実行されていることを考えることを引き起こすことを推測します。私が見つけた 唯一の回避策は、新しい配列またはこのような別のオブジェクト内の解決応答をラップすることです:

static fetch(query = {}, opts = {}) { 
    return new Promise((resolve, reject) => { 
    setTimeout(() => { 
     resolve([new this(query)]) 
    }, 500) 
    }) 
} 
// Output 
// 2 
// <-_attributes 
// {"test":"test"} 

私は、これが正しい方法です思ったんだけど、そこには、この副作用に他のソリューションがありますか?約束の結果は常にそれがthen性質を持っているかどうかがチェックされるように渡さ

+1

あなたは今見ている動作に間違いがありますか? 'resolve'に渡される値は' 'thenable 'なので、' .then'が存在するかどうかを調べます。それは期待される。 – loganfsmyth

+0

何も間違っているわけではありませんが、これが期待された動作であるかどうか、それを回避する方法があるのだろうかと思っていました。それは、パフォーマンスが疑わしい場合があるため、不必要な代理コールを防止したいということです。 –

+0

"*' new this(query) 'で解決すると、約束が返されていると思うかもしれません。 "* ...そして結果的に' .then() 'が実行されます*" - いいえ、存在しないため実行されません。しかし、それがメソッドの場合に実行するために*試して*アクセスされます。 – Bergi

答えて

1

すべてのオブジェクト。そうであれば、その関数はエントリをキューに入れて最終的な値を得るために使われます。これは

Promise.resolve() 
    .then(() => { 
     return Promise.resolve(45); 
    }) 
    .then(result => { 
     console.log(result); 
    }); 

ログ代わりに約束オブジェクトの45のような理由の論理です。 promiseオブジェクトには.thenプロパティがあるため、promises値のラップを解除するために使用されます。同じ動作が、resolve(new this(query))のケースで発生します。なぜなら、アンラップする値があるかどうかを知る必要があるからです。あなたが言ったように

は、投稿にコメントし、あなたは確かに非プロキシ、例えばとインスタンスをラップすることができそのオブジェクトではなく、プロキシに.thenをチェックしたが、その後、あなたが実際に痛みをすることができ、プロキシを取得するには.valueをしなければならないでしょう

resolve({ value: new this(query) }) 

一日の終わりには、それはあなたが作る必要があるでしょう選択肢です。

+0

あなたの答えを受け入れるでしょう。ハンド。私はこれのようなものを疑ったが、いつも確認するのは良いことだ。とにかく私はただ待っていた約束の上でデストラクタを使うだけで、それは醜い.valueを持たないでそのトリックをするでしょう。次のようなものです:const [user] =待ち受けUser.fetch({username}) –