[英]Higher-order folder function using callbacks
我想編寫一個給出函數列表的函數,將遍歷該列表,逐步將每個閉包的結果傳遞給下一個閉包。
列表中函數的函數簽名類似於(偽代碼):
typealias DoneClosure = (Dictionary) -> Void
typealias Middleware = (Dictionary, DoneClosure) -> Void
我會有一個類型Middleware
的列表,我想從左到右縮小,折疊整個列表並將每個閉包的結果傳遞到下一個閉包。
let middleware1 = { acc, done in
// do something with acc, modify it
done(acc)
}
每個函數看起來都與此類似,它們以某種方式修改累加器,然后將結果傳遞給done或next函數。
我正在尋找的是一個遞歸函數,它可以使用回調在列表中折疊,因此可以處理異步。 誰能幫我嗎? (語言無關緊要,但首選JS或Swift)。
// 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獲得類似的結果。
我能夠使用遞歸來解決它(在Swift中)
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)
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.