异步库是否有任何用于处理管道的控制流?

时间:2015-12-07 23:36:35

标签: javascript pipeline async.js

我正在查看async库,但我似乎无法找到处理管道的控制流程。我只是想知道我在这里是否遗漏了什么。

我想实现一个管道。例如:

let pipeline = [];
pipeline.push((input, next) => { next(null, input); });
pipeline.push((input, next) => { next(null, input); });
var pipelineResult = pipelineRunner.run(pipeline, 'sample input', (error, result) => {});

说明:调用一系列函数。每个函数都会收到inputnext函数。每个函数处理input并将其作为参数传递给next函数。作为管道执行的结果,我获得了已处理的input,或者,如果任何函数调用next并出现错误,则管道停止并调用回调。

我想这是一个非常常见的用例,所以我认为async可以做到,但我无法找到它。如果您知道任何其他可以实现此类结果的库,那也是可以接受的。

2 个答案:

答案 0 :(得分:1)

您正在寻找async.waterfall function

如果您需要一个可以将初始input传递给的函数,则可以apply asyc.seqasync.compose使用多个参数。

答案 1 :(得分:0)

我最终自己实现了它,尽管如@Bergi所示,/** * Runs asynchronous pipelines */ class PipelineRunner { /** * Runs the given pipeline * @param pipeline - The array of functions that should be executed (middleware) * @param middlewareArgs - The array of arguments that should be passed in to the middleware * @param input * @param next */ run(pipeline, middlewareArgs, input, next) { if (!pipeline) throw Error('\'pipeline\' should be truthy'); if (!context) throw Error('\'context\' should be truthy'); if (!input) throw Error('\'input\' should be truthy'); if (!next) throw Error('\'next\' should be truthy'); if (!pipeline.length) throw Error('\'pipeline.length\' should be truthy'); let index = 0; // the link function "binds" every function in the pipeline array together let link = (error, result) => { if (error) { next(error); return; } let nextIndex = index++; if (nextIndex < pipeline.length) { let args = [result].concat(middlewareArgs).concat(link); pipeline[nextIndex].apply(null, args); } else { next(null, result); } }; let args = [input].concat(middlewareArgs).concat(link); pipeline[index++].apply(null, args); } } export default new PipelineRunner(); 确实支持它。

import chai from 'chai';
import pipelineRunner from '../src/server/lib/pipelines/pipelineRunner';
let assert = chai.assert;


describe('PipelineRunner', () => {
    describe('run', function() {
        it('Happy path', () => {
            let pipeline = [];
            pipeline.push((input, next) => { next(null, input); });
            pipeline.push((input, next) => { next(null, input); });

            pipelineRunner.run(pipeline, [], 'happy', (error, result) => {
                assert.strictEqual(result, "happy");
            });
        });

        it('Happy path - with arguments', () => {
            let pipeline = [];
            pipeline.push((input, someArgument, next) => {
                assert.strictEqual(someArgument, 'something that should be passed in');
                next(null, input);
            });
            pipeline.push((input, someArgument, next) => { next(null, input); });

            pipelineRunner.run(pipeline, ['something that should be passed in'], 'happy', (error, result) => {
                assert.strictEqual(result, "happy");
            });
        });

        it('When something goes wrong', () => {
            let pipeline = [];
            pipeline.push((input, next) => { next(null, input); });
            pipeline.push((input, next) => { next('something went wrong'); });

            pipelineRunner.run(pipeline, [], 'happy', (error, result) => {
                assert.strictEqual(error, 'something went wrong');
            });
        });
    });
});

单元测试

Collections.sort(Comparator<? super Customer>...)