Node.js中如何并行执行Cloudant查询及相关报错问题解决
问题解决方法
报错原因
你传入async.parallel的任务列表直接填写了service.postFind(query1)执行后的返回值(Promise对象),而async.parallel要求任务列表的每一项必须是可执行的函数,运行时它尝试把传入的Promise当作函数调用,就抛出了fn is not a function的类型错误。
同时你的代码还有两处隐含问题:
- 定义查询条件时的连续赋值
CloudantV1.Selector = {...}会覆盖Cloudant SDK的全局Selector属性,属于错误写法 - 结果处理时的
body[0].docs不符合CloudantpostFind接口的返回结构,正确的文档列表存放在result.docs字段下
实现方案1:原生Promise.all(推荐)
你的doGet本身已经声明为async函数,直接用JS原生的Promise.all就能实现并行查询,无需引入第三方async库,代码更简洁:
doGet : async (request, response) => { try { const usersState = []; // 修正查询条件的赋值写法 const queryForCricket = { "hoby": "Cricket" }; const queryForChess = { "hoby": "Chess" }; const query1 = { db: dbName, selector: queryForCricket, fields: ["_id", "name", "hoby" ], limit: 50, skip: 0 }; const query2 = { db: dbName, selector: queryForChess, fields: ["_id", "name", "hoby" ], limit: 50, skip: 0 }; // 并行执行两个查询,等待所有请求返回 const [cricketRes, chessRes] = await Promise.all([ service.postFind(query1), service.postFind(query2) ]); // 合并两个查询的结果 cricketRes.result.docs.forEach(doc => doc && usersState.push(doc)); chessRes.result.docs.forEach(doc => doc && usersState.push(doc)); response.send({ "usersState": usersState, "message": "ok" }); } catch (err) { // 任意查询失败都会进入catch分支 response.send({ "message": "Get operation failed" }); } }
实现方案2:修正async.parallel写法
如果要继续使用async库,需要把每个查询任务包裹成匿名函数返回:
async.parallel( [ // 每个任务项是返回Promise的函数,不要直接执行postFind () => service.postFind(query1), () => service.postFind(query2) ], function (err, results) { if (err) { response.send({ "message": "Get operation failed" }); return; } const usersState = []; results.forEach(res => { // 修正结果取值路径 res.result.docs.forEach(doc => doc && usersState.push(doc)); }); response.json({ "usersState": usersState, "message": "ok" }); } );
内容的提问来源于stack exchange,提问作者Jayden
相关产品推荐
相关产品推荐

