2017-03-13 4 views
1

私は、連鎖配列を約束するために成長してきました。各約束はこれを読み、信じられないほど簡単です長いようなプロミスチェーンを読みやすくする

myArray.map(x => convertX) 
    .filter() 
    .whatever() 
    .etc() 

ラインがあるとき、それは約束チェーンを読むために非常に簡単です。しかし、カスタム関数を使って約束チェーンを作成すると、それはずっと面倒です。

database.query(first query) 
    .then(results => { 
    // do stuff 
    // do more 
    // even more 
    return database.query(second query) 
    }) 
    .then(results => { 
    // rinse and repeat 
    }) 
    .catch(err => { 
    // error handling 
    }) 

これはわかりやすいですが、将来の約束がさらに伸びると、やや大きめになります。私はそれぞれの約束を自分自身のものにすると、プロセスを合理化して、コードがこのように見えるようにすることができます(これは、1000倍の読みやすさです)。

db.query(first query) 
    .then(storeFirstQuery) 
    .then(secondQueryAndStoreIt) 
    .then(thirdQueryAndStoreIt) 
    .catch(errHandlingFunction) 

この方法で、私は次の1つの約束から渡される値を操作することなく、機能を並べ替えることができます。約束が別のものの結果を使用している場合、それは他のものの後にある必要がありますが、すぐ後ではありません。そうすれば私はどこにでも約束をこっそり入れることができます。

しかし、これは私の約束がそれぞれの約束の範囲外の変数を使用するために必要です。これを行うには、試して真の方法がありますか?

編集 - これを行うための最善の方法ですが、私はHerokuの上のノードを実行していることだし、それはまだサポートされていないasync/awaitようだ:/

+0

あなたが選んだアプローチが一番好きではないようです。わかりません、それは読みやすいJavaScriptなので、読みやすい英語です。それは["コールバックライト"](http://stackoverflow.com/a/42380006/918910)です。 – jib

答えて

1

さて、あなたが約束しているようなものを使用することができます。

myArray.map(x => convertX) 
    .filter() 
    .whatever() 
    .etc() 

あなたがnpmのrspモジュールを使用している場合は、

これ以外にも、約束のチェーン、特にその範囲を簡略化するために、async/awaitというES2017の機能を使用することができます。

ため、次のようなコードを持つ:

db.query(first query) 
    .then(storeFirstQuery) 
    .then(secondQueryAndStoreIt) 
    .then(thirdQueryAndStoreIt) 
    .catch(errHandlingFunction) 

あなたが最後thirdQueryAndStoreIt()ハンドラで最初のクエリの結果を使用する必要がある場合は、スコープの外にあるデータへのアクセスに問題があります。しかし、あなたが行うとき:あなたは簡単に以前に割り当てられたすべての変数にアクセスすることができますよう

try { 
    let a = await db.query(first query); 
    let b = await storeFirstQuery(); 
    let c = await secondQueryAndStoreIt(); 
    let d = await thirdQueryAndStoreIt(a); // use 'a' here 
} catch (e) { 
    errHandlingFunction(e); 
} 

は、あなたは、スコープの問題を持っていません。

この構文をサポートするノードのバージョンのためにこれを参照してください:

あなたが箱から出したりとノードV7.0の+とノードv7.6 +でそれを使用することができます

--harmonyフラグ。

旧バージョンのノードでは、またはBluebird.coroutineを、ジェネレータ関数を使用した同様の構文に使用し、awaitの代わりにyieldを使用できます。

+0

そうです、 'async' /' await'はそれを行う最良の方法のようです。残念ながら、私はNode on Herokuを実行していますが、まだサポートされていません。 – Matt

+0

あなたはasync/awaitなしでまったく同じことができます。それはちょうど目のキャンデーです。 – Tomalak

-1

あなたが本当にしたい場合、あなたはそれを自分で作成することによって、単一のメタ約束に範囲を限定することができます

return new Promise((resolve, reject) => { 
    const f1 =() => { /* ... */ }; 
    const f2 =() => { /* ... */ }; 
    const f3 =() => { /* ... */ }; 

    return db.query() 
    .then(f1) 
    .then(f2) 
    .then(f3) 
    .then(resolve) 
    .catch(reject); 
}); 

が、これを行うには、最も読みやすい方法はasync/awaitを使用することです。

+0

私は、Heroku上で実行されているノードサーバーでこれをすべてやっていると付け加えておきます。彼らは 'async' /' await'をまだサポートしていません:/ – Matt

+0

@matt Hm?この回答には非同期/待機がありません。 – Tomalak

+1

@ダン "メタ・プロミス"をしないでください。クロージャを作成し、それから元の約束を返すために、通常の関数(IIFE)を使用してください。 – Tomalak

関連する問題