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