求异步大神分析一下这段代码的几个callback分别代表什么意思

微醺岁月
  • 2.9k

看着头晕,一个异步模块开源项目的代码,回调有点绕,都理不清各自的callback了,异步大神帮忙分析一下这段代码。

const fs = require('fs')

const files = ['./file/1.js', './file/2.js', './file/3.js']

function series(tasks, callback) {
    callback = callback || function() {}
    let results = Array.isArray(tasks) ? [] : {}

    eachOfSeries(tasks, function(task, key, callback) {
        task(function(err, data) {
            results[key] = data 
            callback(err)
        })
    }, function(err) { 
        callback(err, results) 
    })
}


series([function(callback) {
    fs.access('./file/1.js', function(err) {
        callback(null, err ? false : true)
    });
}, function(callback) {
    fs.readFile('./file/2.js', function(err, data) {
        callback(err, data)
    });
}], function(err, results) {
    if (err) {
        throw err;
    }
    console.log(results);
});


function eachOfSeries(arr, fn, callback) {
    callback = callback || function() {}
    arr = arr || []

    let i = -1
    let sync = true
    next()

    function next() {
        sync = true

        if (++i == arr.length) {
            return callback()
        }
        fn(arr[i], i, once(done))

        sync = false
    }

    function done(err) {
        if (err) {
            return callback(err)
        }
        if (sync) {
            setImmediate(next)
        } else {
            next()
        }
    }

    function once(fn) {
        return function() {
            if (!fn) {
                return
            }
            fn.apply(this, arguments)
            fn = null
        }
    }
}
回复
阅读 2k
2 个回答
✓ 已被采纳
const fs = require('fs')

const files = ['./file/1.js', './file/2.js', './file/3.js']

function series(tasks, callback) {
        // 1.参数有 callback 的话就取 callback 没有就赋值一个空函数
    callback = callback || function() {}
    let results = Array.isArray(tasks) ? [] : {}

    eachOfSeries(tasks, function(task, key, callback) {
        task(function(err, data) {
            results[key] = data 
            // 调用eachOfSeries里面的 callback 把 err 作为参数
            callback(err)
        })
    }, function(err) { 
            // 调用1的上面callback 把 err,results 作为参数
        callback(err, results) 
    })
}


series([function(callback) {
    fs.access('./file/1.js', function(err) {
            // 数组第一个函数的参数 callback
        callback(null, err ? false : true)
    });
}, function(callback) {
    fs.readFile('./file/2.js', function(err, data) {
            // 数组第二个函数的参数 callback
        callback(err, data)
    });
}], function(err, results) {
    if (err) {
        throw err;
    }
    console.log(results);
});


function eachOfSeries(arr, fn, callback) {
        // 2.参数有 callback 的话就取 callback 没有就赋值一个空函数
    callback = callback || function() {}
    arr = arr || []

    let i = -1
    let sync = true
    next()

    function next() {
        sync = true

        if (++i == arr.length) {
            return callback()
        }
        fn(arr[i], i, once(done))

        sync = false
    }

    function done(err) {
        if (err) {
                // 返回 第二个 callback
            return callback(err)
        }
        if (sync) {
            setImmediate(next)
        } else {
            next()
        }
    }

    function once(fn) {
        return function() {
            if (!fn) {
                return
            }
            fn.apply(this, arguments)
            fn = null
        }
    }
}

如果你有个比较好用的编辑器,通过重命名重构很容易就能把关系理清楚,下面的代码是用 VSCode 重命名的

const fs = require("fs");

const files = ["./file/1.js", "./file/2.js", "./file/3.js"];

function series(tasks, callback_1) {
    callback_1 = callback_1 || function() { };
    let results = Array.isArray(tasks) ? [] : {};

    eachOfSeries(tasks,
        function(task, key, callback_2) {
            task(function(err, data) {
                results[key] = data;
                callback_2(err);
            });
        },
        function(err) {
            callback_1(err, results);
        });
}


series([
    function(callback_3) {
        fs.access("./file/1.js", function(err) {
            callback_3(null, err ? false : true);
        });
    },
    function(callback_4) {
        fs.readFile("./file/2.js", function(err, data) {
            callback_4(err, data);
        });
    }],
    function(err, results) {
        if (err) {
            throw err;
        }
        console.log(results);
    });


function eachOfSeries(arr, fn, callback_5) {
    callback_5 = callback_5 || function() { };
    arr = arr || [];

    let i = -1;
    let sync = true;
    next();

    function next() {
        sync = true;

        if (++i == arr.length) {
            return callback_5();
        }
        fn(arr[i], i, once(done));

        sync = false;
    }

    function done(err) {
        if (err) {
            // 返回 第二个 callback
            return callback_5(err);
        }
        if (sync) {
            setImmediate(next);
        } else {
            next();
        }
    }

    function once(fn) {
        return function() {
            if (!fn) {
                return;
            }
            fn.apply(this, arguments);
            fn = null;
        };
    }
}
你知道吗?

宣传栏