2017-05-13 13 views
3

関数のリストを指定してそのリストを折りたたみ、各クロージャの結果を次の関数に徐々に渡す関数を記述したいと思います。コールバックを使用した上位のフォルダ関数

リスト内の関数の関数シグネチャは(擬似コード)のようになります。

typealias DoneClosure = (Dictionary) -> Void 
typealias Middleware = (Dictionary, DoneClosure) -> Void 

私はタイプMiddlewareのリストを持っているでしょうし、私は左から右に削減したい、全体の折りたたみリストを作成し、各クロージャの結果を次のクロージャに渡します。

let middleware1 = { acc, done in 
    // do something with acc, modify it 
    done(acc) 
} 

各機能はこれと似ていますが、何らかの方法でアキュムレータを変更し、その結果をdoneまたは次の関数に渡します。

私が探しているのは、コールバックを使用してリスト全体を折り畳み、非同期に処理できる再帰関数です。誰か助けてくれますか? (言語は無関係ですが、JSまたはSwiftが優先されます)。

+0

は、既に持っていますか? – dandavis

+0

私はこの約束をどこにも書いていません。残念なことに、 – barndog

+0

あなたはコードのいくつかの行で基本的な約束事を書くことができます。パターンは重要です。具体的には、 'Promise()'と ' Promise.all() 'など何か_like_ – dandavis

答えて

3
// does not handle empty middlewareList 
const makeFunctionChain = function (middlewareList, initalDic) { 
    const length = middlewareList.length; 
    let i = 0; 
    let middleware; 

    const next = function (localAccumulator) { 
     middleware = middlewareList[i]; 
     i += 1; 
     if (i === length) { 
      // there is no next 
      // pass a do-nothing function 
      middleware(localAccumulator, function() {}); 
     } else { 
      middleware(localAccumulator, next); 
     } 
    }; 
    next(initalDic); 
}; 

// usage example 

const middlewareAddOnions = function (food, next) { 
    // simple middleware 
    food["onions"] = 3; 
    next(food); 
}; 

const middlewareAddWater = function (food, next) { 
    // here we use a new accumulator 
    const newFood = Object.assign({}, food, {withWater: true}); 
    next(newFood); 
}; 

const middlewareCook = function (food, next) { 
    // next can also be called asynchronously. 
    // here we use setTimeout 
    const timeToCook = 1500; 
    setTimeout(function() { 
     food.cooked = true; 
     next(food); 
    }, timeToCook); 
}; 

const middlewareServe = function (food, next) { 
    // here we read the data 
    // does not use next 
    if (food.cooked) { 
     console.log(`Time to eat: ${JSON.stringify(food)}`); 
    } else { 
     console.log(`Something went wrong: ${JSON.stringify(food)}`); 
    } 
}; 


// time to try it out 
const food = { 
    eggs: 4, 
    potatoes: 12, 
    // ... 
}; 

makeFunctionChain([ 
    middlewareAddOnions, 
    middlewareAddWater, 
    middlewareCook, 
    middlewareServe 
    ], food); 

コメントに記載されているように、Promisesを使用しても同様の結果が得られる可能性があります。彼らはあなたのために働くん同じ形状の約束です

0

私は(スウィフトで)再帰を使用してそれを把握することができた

typealias Next = (JSON) ->() 
typealias JSON = [String: Any] 
typealias Middleware = (JSON, Next) ->() 

func process(middlewareList: [Middleware], value: JSON, done: @escaping Next) { 
    guard !middlewareList.isEmpty else { 
     done(value) 
     return 
    } 
    let middleware = middlewareList.first! 
    let slice = Array(middlewareList[1..<middlewareList.count]) 
    middleware(value) { json in 
     process(middlewareList: slice, value: json, done: done) 
    } 
} 

let hook1: Middleware = { json, done in 
    print("hook 1") 
    done(json) 
} 

let hook2: Middleware = { json, done in 
    print("hook 2") 
    var copy = json 
    copy["hi"] = "hi" 
    done(copy) 
} 

process(middlewareList: [hook1, hook2], value: [:], done: { json in 
    print(json) 
}) 
関連する問題