2017-08-01 6 views
-1

私は、promisified dynogelsを使用してDynamoDBからデータを取り出し、オブジェクトのプロパティの一部を取り込むコンストラクタを持っています。 だから、そのオブジェクトのインスタンスをインスタンス化した後に、プロパティが設定されません、ここでのコードの抜粋である:ノードコードがブロックされていませんか?

export class QueryAuthoriser { 
    authPerms: [AuthPerms]; 

    constructor (data: string) { 
    AuthPermsDDB.scan().execAsync().then ((perms) => { 
     perms.Items.forEach(element => { 
     this.authPerms[element.name] = <AuthPerms> element.attrs 
     }) 
    }).catch (err => { 
     console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err) 
    }) 
    } 

    authFieldAccess (fieldName: string, args?:any): Promise<boolean> { 
    return new Promise ((resolve, reject) => { 
     console.log ('________________ authFieldAccess called for: ', fieldName) 
     console.log ('________________ this.authPerms entry: ', this.authPerms[fieldName]) 
     resolve (true) 
    }) 
[...] 
} 

authFieldAccessメソッドが呼び出されたときに、フィールドthis.authPermsは未定義です。これをどうすれば解決できますか?

おかげで、私は、ノードを学習し、ハードな方法を活字体だ:Oそれは知っている、オブジェクトの作成複雑にしているので

答えて

1

あなたは、一般的にコンストラクタで非同期操作を実行したくない場合に非同期操作またはコンストラクターがオブジェクトを返すことを許可する必要があるためにエラーが発生した場合、非同期操作がいつ行われたかを示す約束ではありません。

オプション#1:

は、いくつかの可能な設計オプションがあり、コンストラクタ内の任意の非同期操作をしないでください。次に、非同期操作を行う適切な名前の新しいメソッドを追加し、約束を返します。

あなたの場合、約束を返す新しいメソッドをscan()にすることができます。次に、オブジェクトを作成してスキャンを呼び出し、返された約束を使用してデータが有効であることを知ることでオブジェクトを使用します。

それは活字体またはプレーンのJavascriptのかどうか私は活字体を自分自身を知らないので、私はあなたのコードの修正バージョンをあげるが、考え方は同じいずれかの方法である:

export class QueryAuthoriser { 
    authPerms: [AuthPerms]; 

    constructor (data: string) { 
    } 

    scan() { 
    return AuthPermsDDB.scan().execAsync().then ((perms) => { 
     perms.Items.forEach(element => { 
     this.authPerms[element.name] = <AuthPerms> element.attrs 
     }) 
    }).catch (err => { 
     console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err) 
    }) 
    } 

} 

// usage 
let obj = new QueryAuthoriser(...); 
obj.scan(...).then(() => { 
    // the object is full initialized now and can be used here 
}).catch(err => { 
    // error here 
}) 

オプション#2 :コンストラクタで非同期操作を開始し、呼び出し元のためにインスタンスデータ内に約束を使用して、すべてが完了したときを知る。

export class QueryAuthoriser { 
    authPerms: [AuthPerms]; 

    constructor (data: string) { 
    this.initialScan = AuthPermsDDB.scan().execAsync().then ((perms) => { 
     perms.Items.forEach(element => { 
     this.authPerms[element.name] = <AuthPerms> element.attrs 
     }) 
    }).catch (err => { 
     console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err) 
    }) 
    } 

} 

// usage 
let obj = new QueryAuthoriser(...); 
obj.initialScan.then(() => { 
    // the object is full initialized now and can be used here 
}).catch(err => { 
    // error here 
}); 

オプション#3:オブジェクト自体に解決の約束を返すファクトリ関数を使用します。

export createQueryAuthorizer; 

function createQueryAuthorizer(...) { 
    let obj = new QueryAuthorizer(...); 
    return obj._scan(...).then(() => { 
     // resolve with the object itself 
     return obj; 
    }) 
} 

class QueryAuthoriser { 
    authPerms: [AuthPerms]; 

    constructor (data: string) { 
    } 

    _scan() { 
    return AuthPermsDDB.scan().execAsync().then ((perms) => { 
     perms.Items.forEach(element => { 
     this.authPerms[element.name] = <AuthPerms> element.attrs 
     }) 
    }).catch (err => { 
     console.log ('%%%%%%%%%%%%%% Err loading authPerms: ', err) 
    }) 
    } 

} 

// usage 
createQueryAuthorizer(...).then(obj => { 
    // the object is fully initialized now and can be used here 
}).catch(err => { 
    // error here 
}); 

私の好みは、いくつかの理由オプション#3ためです。他のスキームですべての呼び出し側が行う必要があるファクトリ関数内の共有コードを取得します。また、オブジェクトが適切に初期化されるまで、オブジェクトへのアクセスを防止します。他の2つのスキームは、ドキュメンテーションとプログラミングの規律を必要とし、容易に誤用される可能性があります。

+0

ありがとう@ jfriend00、それはうまく動作します。このコードは 'createQueryAuthorizer'メソッドをブロックしますが、私の意図はDBへの非同期呼び出しを行い、最初にデータを必要とするのを待つだけですが、データは数回必要となるため初めてです。私は実装を変更しようとします。 –

+0

@CarlosDelgado - ここには何もブロックされていないので、あなたはそれが何を意味するのかよく分かりません。 'createQueryAuthorizer()'メソッドはすぐに戻り、約束を返します。オブジェクトが適切に初期化されるまで、オブジェクトを使用することはできません。コードの他の部分も同じオブジェクトを使用したい場合、同じ約束を待つことができます。 – jfriend00

関連する問題