JavaScriptの遅延関数

こんにちは







Flutureライブラリを使用してJavaScriptで遅延関数を作成および使用する方法について説明するために、ここで考えました。 これは、関数の作成方法、エラーの処理方法、および同時実行性についての簡単な概要です。 関数型プログラミングの頭脳は急上昇しません! 約束します!







Fluture



Flutureは、開発者Aldwin Vlasblomが開発した、Futureを実装するライブラリです。 Futureは、キャンセル、安全な「再帰」、「エラーのない」実行(いずれかを使用)、およびクールな機能の小さな台車を実装できるはるかに強力なAPIを備えたPromiseの代替です。







以下の例で使用するメソッド(モナド)について説明する価値があると思います。









遅延関数を作成する



私自身は、Fltureで遅延関数を作成するための2つの主なアプローチを強調しました。 最初のアプローチは、ソースデータを受け取り、実行可能なFutureを返す関数を作成することです。 2番目のアプローチは、記述されたすべての変換を使用してFutureを作成し、データをそれに渡します。







はっきりしない 例を見てみましょう! このような機能があります







 const multiply10 = x => x * 10;
      
      





最初のアプローチを使用して彼女を怠zyにします







 const multiply10 = x => x * 10; const lazyMultiply10 = (x) => Future .of(x) //  Future   .map(multiply10); //     lazyMultiply10(2).fork(console.error, console.log); // -> 20
      
      





かさばりすぎではありませんか? 2番目のアプローチを使用して、より簡潔に記述してみましょう。







 const multiply10 = x => x * 10; const lazyMultiply10 = Future.map(multiply10); const value = Future.of(2); //     Future lazyMultiply10(value).fork(console.error, console.log); // -> 20
      
      





すでに優れていますが、それでも面倒です。 もっとコンパクトでなければなりません!







 const lazyMultiply10 = Future.map(x => x * 10); lazyMultiply10(Future.of(2)).fork(console.error, console.log); // -> 20
      
      





実際、これらのアプローチは相互に排他的ではなく、一緒に使用できます。







 const lazyMultiply10 = Future.map(x => x * 10); const someCalculation = a => Future .of(a) .map(v => v + 1) .chain(v => lazyMultiply10(Future.of(v)); someCalculation(10).fork(console.error, console.log); // -> 110
      
      





エラー処理



Futureのエラー処理は、Promiseのエラー処理と実質的に同じです。 しましょう 覚えている 非常に安定していないサードパーティのAPIにリクエストを行う関数を想像してください。







 const requestToUnstableAPI = query => request({ method: 'get', uri: `http://unstable-site.com/?${query}` }) .then(res => res.data.value) .catch(errorHandler);
      
      





同じ機能ですが、未来に包まれています







 const lazyRequestToUnstableAPI = query => Future .tryP(() => request({ method: 'get', uri: `http://unstable-site.com/?${query}` })) .map(v => v.data.value) .chainRej(err => Future.of(errorHandler(err));
      
      





実際、エラー処理の柔軟性を高めることができます。 これを行うには、どちらかの構造が必要であり、この小ささはレビューの範囲を超えています。







並行性



並列処理を行うために、Futureは2つのメソッドrace(Futures[])



Promise.race



類似)、 parallel(n, Futures[])



、およびboth(Future, Future)



実装していますが、これはparallel



特殊なケースです。







parallel



メソッドは、並列Futureの数とFutureの配列の2つの引数を取ります。 parallel



動作をPromise.all



メソッドと同じにするには、 Promise.all



回数をInfinity



に設定する必要があります。







ここでも、例がなければできません。







 const requestF = o => Future.tryP(() => request(o)); const parallel1 = Future.parallel(1); const lazyReqs = parallel1( [ 'http://site.com', 'http://another-site.com', 'http://one-more-site.com', ] .map(requestF) ); lazyReqs.fork(console.error, console.log); // -> [Result1, Result2, Result3]
      
      





Promise互換



JavaScriptにはPromiseの場所がありません。メソッドがあいまいなFutureを返す場合、誰もが満足することはほとんどありません。 これを行うために、Futureには.promise()



メソッドがあり、Futureの実行を開始してPromiseでラップします。







 Future .of(10) .promise(); // -> Promise{value=10}
      
      





参照資料





おそらく、私があなたに伝えたかったのはそれだけです。 トピックが興味深い場合は、お知らせください。エラー処理について詳しく説明します。 そして、はい、あまり私をscられないでください、これはHabréに関する私の最初の投稿です。








All Articles