約束の鎖は素晴らしいです


ああ、あなたは約束のためにここに来ましたか?はい、私たちは1秒でそれを取得しますが、最初に私はあなたと私の仲間を紹介しましょうトレースと呼ばれる
const trace = tag => x =>
  console.log(tag, x) || x;
これで出会った@drBoolean ジャムは数年前に戻ってsortaヒット.私たちは共通点がたくさんあると理解しました:私たちは両方ともアイデンティティの強い感覚を持っていますが、求めたとき、少しの変更を効果的にするのを恐れません.キッドもカレーを作る.
trace :: Show t => t -> a -> a
を参照してください、トレースについてのことは、彼はどこに彼を置く気にしない、彼はちょうど自分のことを行うに満足している.種類の流れ、約束で行く!
['a', 'b', 'c']
  .map(trace('what do we have here...'))

// what do we have here ... a
// what do we have here ... b
// what do we have here ... c
配列の上にマップされた配列Array#Map
const handleAsJson = resp => resp.json()

fetch(`/users`)
  .then(handleAsJson)
  .then(trace('all users: '))

// all users: [{ id: 1, isAdmin: false }, { id: 2, isAdmin: true }]
との約束に写像Promise#then
痕跡は一見一見、おそらく軽薄であるかもしれません.しかし、その単純さはその力の下にあります.それは、より大きくてより大きい計算に手を貸す単純な、原子、一つの目的マルチ使用機能の一種です.
とにかく、私はここで側面追跡されています.
それで、ある日、トレースと私は晩餐会を主催することに決めました.私たちはその仕事を短時間のリストに分けた
  • ゲストリストを作成
  • 招待状を出す
  • 注文成分
  • 料理をする
  • 夕食を出す
  • const handleAsJson = resp => resp.json()
    const map = f => xs => xs.map(f)
    const all = Promise.all.bind(Promise)
    
    const fetchGuests = () => fetch('/friends')
    const fetchShoppingList = () => fetch('/shopping-list')
    const order = item => fetch(`https://groceries.for.you/order/${item}`)
    const invite = body => to =>
      fetch(`/sendmail?to="${encodeURIComponent(to)}`, { method: 'POST', body })
    
    const getEmail = ({ email }) => email
    const cook = xs => xs.reduce(fricassee, 'a delicious ')
    const serve = dish => alert(`${dish} is served!`)
    const fricassee = (a, x, i, {length}) =>
      `${a}-${x}${i === length - 1 ? ' fricassee' : ''}`
    
    function party() {
      return fetchGuests()
        .then(handleAsJson)      // Promise<[person]>
        .then(map(getEmail))     // Promise<[string]>
        .then(map(invite))       // Promise<[Response]>
        .then(all)               // Promise<[invitation]>
        .then(fetchShoppingList) // discard previous result, as `fetchShoppingList` takes no arguments.
        .then(handleAsJson)      // Promise<[item]>
        .then(map(order))        // Promise<[Promise<order>]>
        .then(all)               // Promise<[order]>
        .then(cook)              // Promise<Fricasee>
        .then(serve)             // et voila
    }
    
    私にとって、右上から右上へのこの種の流れは、読みやすくて、美しいです.一度に一つの事を追跡する必要があるだけですthen コール.
    しかし、この流れは真実のVSコードの独裁的なo - matic電球の外で走ります™️

    代わりに
    async function party() {
      const guestsResponse = await fetchGuests()
      const guests = await guestsResponse.json()
      const emails = guests.map(getEmail)
      const inviteResponses = emails.map(invite)
      const listResponse = fetchShoppingList()
      const list = listResponse.json()
      const orderPromises = list.map(order)
      const orderResponses = Promise.all(orderPromises)
      const order = orderResponses.map(handleAsJson)
      const dish = cook(order)
      return serve(dish)
    }
    
    どのように多くの州は、どのように多くのステートメントは、どのくらいの精神的な実行は、レッドモンドで我々の様式主義的な貴族をなだめるために必要となるだろうか?

    閉鎖による割当


    あなたが個別に自分の食事のニーズに敬意を払ってそれぞれを提供することができますので、ユーザーを追跡する必要があると言う.閉じるこの動画はお気に入りから削除されています.今は閉鎖の技術的な定義を混乱させる時ではありません.
    const all = Promise.all.bind(Promise)
    
    const constant = x => () => x
    
    const not = p => x => !p(x)
    
    const fanout = (f, g) => x => [f(x), g(x)]
    const merge = f => ([x, y]) => f(x, y)
    
    const bimap = (f, g) => ([xs, ys]) => [xs.map(f), ys.map(g)]
    
    const serve = dish => guest => alert(`${guest} has been served ${dish}!`)
    
    function party() {
      return fetchShoppingList()
        .then(handleAsJson)
        .then(map(order))
        .then(cook)
        .then(dish => orderDietDishes() // no closing `)`, so dish stays in closure
        .then(handleAsJson)
        .then(dietDish => fetchGuests() // no closing `)`, so dietDish stays in closure
        .then(handleAsJson)
        .then(users => Promise.resolve(users)
        .then(map(getEmail))
        .then(map(invite))
        .then(all)
        .then(constant(users)))
        .then(fanout(filter(hasDiet), filter(not(hasDiet))))
        .then(merge(bimap(serve(dietDish), serve(dish)))))) // end closures from above
    }
    
    注意:この複雑な例では、クロージャを使って点を説明しましたが、実際の生活では、データ型をcrocks フェーディングとマージのための配列の代わりに、またはPOJOが状態を保持するために渡すかもしれません.私も使用await に割り当てるconst , しかし、私はすべてを包むことによって赤ちゃんを浴槽水で投げません.シングル.約束.コールサイトで.

    総括


    よく名前を付けて、単純で、構成可能で、一流の関数は散文のように読むコードにつながります.このような計算の段階を分離することは、実装を機能させるために、あなたのプログラムをより読みやすくて、より簡単にします.
    タプルにフェードアウトし、バイナリ関数をマージするようなテクニックは、'並列'計算を実行したり、純粋な関数に累積状態を渡すのに適しています.非同期関数は、特にクローズの量が管理するのが困難になるとき、それらの場所を持っています、しかし、それらはすべての最後に取って代わるべきではありません.then コール.

    私を約束!


    それで、チェーンが驚くべきものであると約束してください、そして、あなたのコードをより読みやすくして、より良いソフトウェアに貢献してください.あなたが得る次のチャンスは、その小さな電球“いいえありがとう”を伝える-あなたのアプリケーションでの約束のチェーンを作成し、自己記録、モジュラーコードをお楽しみください.

    謝辞と誤り


    前のバージョンは、通過を証明しましたPromise.all ファーストクラスurls.map(fetch).then(Promise.all) ありがとう
    あなたがバインドしなければならない指摘Promise.all あなたがそれを最初のクラスに渡す予定であるならば.ここのスニペットが更新されました.
    ユーザー
    修正された2番目の例では、typo(コメントを参照)を指摘しました.