2016-07-11 6 views
0

私のJavaの熟練した心は、まだJavascriptと約束の使用を理解するのに苦労しています。私は次のセットアップがあります複数の関数の約束によって返された値を正しく再利用する方法

function foo() { 
    return Promise.resolve('foo'); 
} 

関数fooは、機能バーとバズの両方で必要とされている値を返します。

function bar(foo) { 
    // process and use foo 
    return Promise.resolve('bar'); 
} 

function baz(foo,bar) { 
    return Promise.resolve(foo+bar); 
} 

baz()foo()bar()の結果を使用しているので、私はのようにそれらをチェーンしなければなりませんでしたこれは:

foo() 
    .then((foo)=>{ 
     return bar(foo) 
     .then((bar)=>{ 
      return baz(foo,bar); 
     }) 
    }) 
    .then(console.log); 

次の関数の数に応じてbaz(結果も必要です以前の関数の)これは非常にすばやく醜くなるようです。

別の方法がありますが、これは読みやすく/簡単です。

+0

たぶん 'Promise.all'? – gcampbell

+2

promiseオブジェクトは不変です。だから、一度解決されると、ブラウザのタブを閉じる限り、それはそのままです。一度あなたは 'pr = foo();が好きです。 pr.then(function(val){doSomething(val)}) '' val''はpr.then()を何回呼び出したかを変更しません。そうすれば、あなたが望むかもしれない他の多くの関数で、約束の戻り値を共有することができます。 – Redu

答えて

0

ただ非同期/のawait使用:

;(async()=> { 
    const fooResult = await foo() 
    console.log(await baz(fooResult, await bar(fooResult))) 
})() 
+0

これは既にブラウザまたはnode.jsでサポートされていますか?私はこれがまだES7のためのパイプラインにあると思った。 – Rhayene

+0

@Rhayene現在ステージ3に入っていますが、すでにEdgeによってサポートされています。 Babelを使用してコードをコンパイルして、すべてのブラウザで動作させることができます。 –

+0

「ES7」はすでにES2016としてリリースされていますが、async/awaitは含まれていません。現在、TCは来年を目指しています。うまくいけば、彼らはそれを作るでしょう。 –

0

将来非同期構文の必要はありません。私はその機能が虐待を受けるのではないかと怖がっている。

const 
 
    foo =() => 
 
    Promise.resolve('foo') 
 

 
, bar = foo => 
 
    Promise.resolve('bar') 
 

 
, baz = (foo, bar) => 
 
    Promise.resolve(foo + bar) 
 

 
, delay = (ms, p) => 
 
    new Promise(res => 
 
    setTimeout(res, ms, p)) 
 

 
, randWait = p => 
 
    delay(Math.random() * 5000, p) 
 

 
, log = a => console.log(a) || a 
 

 
, str = a => 
 
    JSON.stringify(a, null, 2) 
 
    //Assuming bar needs to be called after foo has returned 
 
    //because of call signature in bar 
 

 
foo().then(f => bar(f).then(b => baz(f, b)).then(log)) 
 

 
//using Promise.all in a block so p doesn't become global 
 
//be carefull to ensure the call order lines up with 
 
//the next then call you can also pass your previous resolved 
 
// promises along in the array 
 
{ 
 
    let p; //temporary holder 
 
    Promise.all([p = foo(), p = p.then(bar)]).then(([f, b]) => 
 
    Promise.all([f, b, baz(f, b)])).then(log) 
 
} 
 

 
//To have named promises you can use an object instead 
 
//of an array if you use something like this 
 
const resolver = o => { 
 
    var keys = Object.keys(o) 
 
    return Promise.all(keys.map(a => o[a])).then((a, i) => 
 
    a.reduce((o, v, i) => 
 
     (o[keys[i]] = v, o), {})) 
 
} 
 

 
, fooPromise = randWait(foo()) 
 

 
, barPromise = fooPromise.then(bar) 
 

 
, bazPromise = resolver({ 
 
    b: barPromise, 
 
    f: fooPromise 
 
}).then(({ 
 
    f, b 
 
}) => baz(f, b)) 
 

 
, annoyingWait = randWait(bazPromise).then(a => 'did you really need to wait for me? ' + a) 
 

 
, all = resolver({ 
 
    annoyingWait, randWait, fooPromise, barPromise, bazPromise, nonPromise: 45, hiMom: delay(4000, 'hi') 
 
}) 
 

 
//Using Await takes a lot of the power away from promises 
 
//because, while it may not block the whole system, it will often 
 
//unneccesarily pause parts of the code. Promises can give you a 
 
//much more fine gain control over async events. 
 

 
, justFooBazAndBar = resolver({ 
 
    foo: fooPromise, 
 
    baz: bazPromise, 
 
    bar: barPromise 
 
}) 
 

 
all.then(str).then(log) 
 

 
justFooBazAndBar.then(log).then(o => 
 
    //merge the object to be available to to the next promise 
 
    //use object.assign because promises results should always 
 
    //be immutable. 
 
    Object.assign({}, o, { 
 
    altBar: bar(o.foo + '2', o.bar + '2') 
 
    })).then(str).then(log)

+0

私の例が不足していたり​​、まだ理解していない(私はまだ初心者です:) :):あなたのPromise.allの例の 'bar(foo)'の 'foo()'の結果ですか? – Rhayene

関連する問題