簡體   English   中英

使用回調的高階文件夾功能

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM