2016-04-28 10 views
0

以下、私はmainの機能を持っています。この関数には他の多くの変数が宣言されており、多くの関数が実行されます。関数内でエラーが発生した場合は、このエラーをキャッチできますが、キャッチ内ではmain関数の値がありません。私はエラーがスローされた場合でもすべての変数にアクセスする方法を探しています。エラーがスローされた場合でも関数内のすべての変数にアクセスできますか?

export async function main ({alpha, beta, gamma}) { 
    let one = await doSomething(alpha) 
    let two = await doSomethingElse(one, beta) 
    return {one, two} 
} 

export async function store (db) { 
    await db.insert(data) 
} 

export async function usage (db, data) { 
    try { 
    let operation = await main(data) 
    await store (db, operation) 
    return operation 
    } catch (e) { 
    // here we don't have access to operation variables :(
    await store(db, {}, e.message) 
    throw e 
    } 
} 

私はこれを行うために見つけた唯一の合理的な方法はmain機能で各値クラスを作成することです。

import { get } from 'lodash' 

export class Operation() { 
    constructor(db){ 
    this.db = db 
    } 
    main({alpha, beta, gamma}) { 
    this.one = await doSomething(alpha) 
    this.two = await doSomethingElse(one, beta) 
    return {one: this.one, two: this.two}  
    } 
    init(data) { 
    try { 
     let main = await this.main(data) 
     await this.store(main) 
     return main 
    } catch (e) { 
     await this.store() 
     throw e 
    } 
    } 
    store(data = {}, errorMessage) { 
    if (!data.one) data.one = get(this, 'one') || null 
    if (!data.two) data.two = get(this, 'two') || null 
    if (errorMessage) data.errMessage = errorMessage 
    return await this.db.insert(data) 
    } 
} 

エラーがスローされた場合でも関数内のすべての変数にアクセスするにはどうすればよいですか?

答えて

0

単純な解決策は、varを使用して、letブロックにスコープされている変数の代わりに関数スコープの変数を宣言することです。私はこのクラスとラッパー機能alwaysRunnerを作成

try { 
    let operation = await main(data) 
    try { 
     await store (db, operation) 
    } catch(e) { 
     // here we do have access to the `operation` variable :) 
    } 
    return operation 
} catch (e) { // failed to create operation (or the inner catch did rethrow) 
    await store(db, {}, e.message) 
    throw e 
} 
+1

は、あなたはまだそれが失敗した場合には、' try'内の最初の 'await'を、お勧めします。 – nrabinowitz

+0

@nrabinowitz:いいえ、私は本当に内側の 'try'の外側に最初の' await'を置くことを意図していたので、例外/拒否は外側の 'catch'ブロックによって捕捉されます。もちろん、猫の皮膚にはさまざまな方法がありますが、これは実際に必要とされるものではないかもしれません。 – Bergi

+0

@Bergi考え方は、 'doSomethingElse'がエラーを投げる場合でも' one'の値にアクセスしたいということです。 – ThomasReggi

0

しかし、あなたは本当にあなたが二つの異なるエラーをキャッチしようとしているとは異なるそれらを処理しようとしているため、2 try/catchステートメントを使用する必要があります。これは2つの関数引数をとり、常に2次関数に利用可能な変数を提供します。

どのように動作するかについていくつかのテストがあります。ちょうど外側のスコープで `operation`のVARを宣言 -

describe('alwaysRunner',() => { 

    it('should work', async() => { 
    let ran = [false, false] 
    await alwaysRunner(function() { 
     ran[0] = true 
     this.alpha = true 
     this.beta = true 
     return this 
    }, function (values) { 
     ran[1] = true 
     assert.equal(values.alpha, true) 
     assert.equal(values.beta, true) 
     assert.equal(values.error, undefined) 
    }).should.not.be.rejected 
    assert.deepEqual(ran, [true, true]) 
    }) 

    it('should work with thrown error', async() => { 
    let ran = [false, false] 
    await alwaysRunner(function() { 
     ran[0] = true 
     this.alpha = true 
     throw new Error('some error') 
     this.beta = true 
    }, function (values) { 
     ran[1] = true 
     assert.equal(values.alpha, true) 
     assert.equal(values.beta, undefined) 
     assert.equal(values.error, new Error('some error')) 
    }).should.be.rejected 
    assert.deepEqual(ran, [true, true]) 
    }) 

}) 
関連する問題