2016-07-27 8 views
-1

非同期関数への参照を含む配列(約束または単純な値を返す)が与えられると、各要素を解決するために、少なくとも1つの要素が真理値に解決されます。少なくとも1つがNode.jsの真理値を返すまで、順次非同期関数のリストを反復する

var hasAccess = (user.isAdmin() || user.isManager() || entity.isOwnedBy(user)); 

上記のコードはうまく同期機能のために動作しますが、非同期のもののために中断します:

アイデアは、この単純な同期コードから来ました。私は上記のコードの非同期置換を探しています。

私はそれが(簡潔にするためにES6構文で)このように呼ばれることを期待:

atLeastOneTruthy([ 
() => user.isAdmin(),  // Called first 
() => user.isManager(),  // Called second if first returned falsy value 
() => entity.isOwnedBy(user) // Called third if all previous returned falsy values 
]).then(function (result) { 
    // result === (true || false) 
}).catch(function() { 
    // Promise chain is rejected when at least one element in rejected 
}); 

例のすべての機能のリターン上の約束または単純な値のいずれかを直接。

このソリューションはすぐに使用できますか?私はBluebirdの約束を使っていますが、私はそれに適したものを見つけることができませんでした。私は使用できません。 Promise.any()です。これは、解決された約束のみをチェックし、戻り値はチェックしないためです。私はPromise.map()を使用することはできません。なぜなら、すべての機能を実行するためですが、必要なとき(つまり前の要素が失敗したとき)にのみ実行することはできません。

ノードモジュールの推奨は素晴らしいです(私は見つけられませんでした)。しかしながら、実装について疑問があるので、atLeastOneTruthy()のコード化のコンセプトも良いでしょう。

答えて

2

ハンドラは約束を返すことができるので、再帰的なソリューションを作ることができます。

function atLeastOneTruthy(arrayOfCallables) { 
    // Keep a numeric index to avoid mutating the input array. 
    // This implementation is not safe for item removal, but appending is OK. 
    let nextCallableIndex = 0; 
    // Start with a false value as a base case. Use a "named function expression" 
    // to allow for recursion. 
    return Promise.resolve(false).then(function innerHandler(returnValue) { 
    if (returnValue) { 
     // If truthy, return immediately. Nothing else is evaluated. 
     return returnValue; 
    } else if (nextCallableIndex < arrayOfCallables.length) { 
     // If falsy, get the next iterable... 
     let nextCallable = arrayOfCallables[nextCallableIndex++]; 
     // ...then call it and try again, regardless of whether nextCallable 
     // returns a simple value or a promise. 
     return Promise.resolve(nextCallable()).then(innerHandler); 
    } else { 
     // We're out of callables, and the last one returned a falsy value. 
     // Return false. (You could also return returnValue to parallel ||.) 
     return false; 
    } 
    }); 
} 

も参照してください:Named function expressions。また、単純なネストされた関数を使用するようにリファクタリングすることもできます。

+1

'then'発現に自身を通過innerHandler'関数式を' @zerkms。これは、関数がスタックに複数回現れるという意味で再帰的ではありませんが、実行が自己参照であるという意味で再帰的です。 –

+0

ああ、確かに、それは私が見落としたものです。 – zerkms

+0

非常に洗練されたソリューション!私は自分自身の "再帰的"実装を終了しましたが、私はあなたのソリューションがより好きです。時間をいただきありがとうございます! ; ) –

0

Promise.any()のような新しいPromiseメソッドを作成することができます。約束事の配列をとり、いずれかが解決しても解決しない場合にのみ解決します。

var one = _ => new Promise((res,rej) => setTimeout(rej.bind(null,"boom"),1000)), 
 
    two = _ => new Promise((res,rej) => setTimeout(rej.bind(null,"crash"),1500)), 
 
    three = _ => new Promise((res,rej) => setTimeout(res.bind(null,"yay..!"),500)); 
 

 
Promise.prototype.constructor.any = function(proms){ 
 
    return proms.length ? proms[0].then(v => v, r => Promise.any(proms.slice(1))) 
 
         : Promise.reject("none resolved"); 
 
}; 
 

 
Promise.any([one(),two(),three()]).then(v => console.log("From promise.any with love",v), r => console.log(r)); 
 
Promise.all([one(),two(),three()]).then(v => console.log(v), r => console.log("From Promise.all with love",r));

関連する問題