2017-05-13 56 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) 
} 

每個功能將類似於此,他們會修改累加器以某種方式,然後傳遞結果到完成或下一個功能。

我在尋找的是一個遞歸函數,它可以使用回調在列表中摺疊,因此可以處理異步。誰能幫我嗎? (語言無關緊要,但首選JS或Swift)。

+0

這是相同的形狀承諾已經,難道他們爲你工作? – dandavis

+0

我正在爲swift編寫這個承諾並不是標準的承諾 – barndog

+0

您可以使用幾行代碼編寫一個基本承諾polyfill,該模式是重要的,特別是您需要重新創建'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); 

正如在評論中指出的那樣,也有可能使用Promise獲得類似的結果。

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) 
})