NodeJS redis多异步读取任务结果操作并汇总返回的递归和非递归实现

512 阅读1分钟
背景

redis数据库连接建立

var redis = require('redis'), 
    RDS_PORT = 6379,
    RDS_HOST = '127.0.0.1',
    RDS_OPTS = {},
    client = redis.createClient(RDS_PORTRDS_HOSTRDS_OPTS);
client.on('ready'function(res) {
    console.log('ready')
});

之后可以通过client.get进行对redis键的索引。当我们用一个键值对存储一个帖子的内容,并且同时要索引多个帖子的内容时,容易直观地写出以下代码

function fn(keys){
    let result = []
    keys.forEach(e => {
        client.get(e, (error, res) => {
            result.push(res)
        })
    })
    return result
}

其中keys表示键名数组。但事实上client.get是一个异步任务,这个函数会直接返回空数组

递归解决方案
function fn(result, index, keys) {
    client.get(keys[index], (error, res) => {
        result.push(res)
        if (index != keys.length - 1) {
            return fn(result, index + 1, keys)
        } else {
            return result
        }
    });
}

const result = fn([], 0, ['key1', 'key2', 'key3'])   //使用
非递归解决方案

anyway,总觉得通过递归解决一些问题(包括二叉树的遍历)有点儿逃避的感觉。虽说JavaScript也支持尾递归优化,但是用递归还是容易写出性能不高的解决方案。因此实现了一个非递归的方法

function fn(keys){
    let promiseTask = []
    let result = []
    keys.forEach(e => {
        let p = new Promise((resolve, reject) => {
            client.get(e, (error, res) => {
                result.push(res)
                resolve()
            })
        })
        promiseTask.push(p)
    })
    Promise.all(promiseTask).then(() => {
        return result
    })   
}

const result = fn(['key1', 'key2', 'key3'])   //使用
一点补充

在实际开发场景中,一般不会直接将取到的键值添加到结果数组,通常要经过某些处理或者过滤。因此建议在函数fn中增加一个参数,用于接收对键值进行处理的方法。这样代码整体结构分明,维护方便。