首页 > 解决方案 > 减少可能是异步且具有回调的函数数组

问题描述

我很好奇如何通过创建函数数组并使用.reduce循环它们来创建 express 中间件的简单版本。

function fullPath(context) {
    context.fullPath = nodePath.isAbsolute(context.path) ? context.path : nodePath.join(context.cwd, context.path);
}

function extension(context) {
    context.extension = nodePath.extname(context.path);
}

function contents(context, callback) {
    return fs.readFile(context.fullPath, { encoding: 'utf8' }, (err, contents) => {
        if (err) throw err;
        context.contents = contents;
        return callback(null, context);
    });
}

function fileLoader(context, callback) {
    return [
        fullPath,
        extension,
        contents
    ].reduce((context, fn) => {
        return fn(context, callback)
    }, context)
}

.reduce循环每个函数,将回调传递给每个函数,并让它们正确嵌套,然后在最后调用父回调的逻辑应该是什么?

标签: javascript

解决方案


这是这个工作:

const nodePath = require('path');
const fs = require('fs');

function fullPath(context) {
    console.log('fullPath')
    context.fullPath = nodePath.isAbsolute(context.path) ? context.path : nodePath.join(context.cwd, context.path);
}

function extension(context) {
    console.log('extension')
    context.extension = nodePath.extname(context.path);
}

function contents(context, callback) {
    console.log('contents')
    return fs.readFile(context.fullPath, { encoding: 'utf8' }, (err, contents) => {
        console.log('contents-i')
        if (err) return callback(err);
        context.contents = contents;
        return callback();
    });
}

function middleware(stack) {
    return (context = {}, master) => {
        var hasError = false
        return stack.reduceRight((callback, fn) => {
            if (hasError) return () => {};
            return () => {
                const isAsync = fn.length === 2
                if (isAsync) {
                    fn(context, (err) => {
                        if (err) {
                            hasError = true
                            return master(err);
                        }
                        callback(null, context);
                    })
                } else {
                    fn(context)
                    callback(null, context)
                }
            }
        }, master)()
    }
}

const fileLoader = middleware([fullPath, extension, contents])

fileLoader({ path: './example.md', cwd: '' }, (err, context) => {
    console.log({ err, context })
})

推荐阅读