如何用Node.js Promise解决CassandraDB client.stream()返回undefined问题
解决Cassandra stream分页返回undefined的异步问题
哈哈,这个异步坑我踩过好多次!你遇到的问题核心就是JavaScript异步操作的执行顺序——client.stream()是基于事件驱动的异步操作,你的foo()函数却是同步执行的,还没等流的end事件触发(也就是数据收集完成),函数就已经执行完return了,所以拿到的自然是undefined。
问题根源拆解
你原来的代码里,end事件回调里的return obj;完全没用,因为这个回调函数的返回值不会被外部的foo()捕获——回调是异步触发的,此时foo()早就执行完并返回了默认的undefined。
解决方案:用Promise封装异步流操作
我们需要把整个stream的事件逻辑封装到Promise里,通过resolve传递最终的结果数组,同时处理错误避免Promise挂起。然后用async/await或者.then()来等待异步操作完成。
修改后的完整代码
function foo() { // 返回一个Promise,让外部可以等待异步操作完成 return new Promise((resolve, reject) => { const resultArray = []; const query = "select username from users where userRank = 3"; client.stream(query, { prepare: true }) .on('readable', function () { let row; // 读取所有可用的行数据 while (row = this.read()) { resultArray.push(row.username); } }) .on('end', function () { // 流结束时,把结果数组传递出去 resolve(resultArray); }) .on('error', function (err) { // 必须处理错误,否则出错时Promise会一直处于pending状态 reject(err); }); }); }
正确的调用方式
你可以用async/await(更直观的同步写法)或者.then()链式调用:
方式1:使用async/await
async function getRankedUsers() { try { const returned = await foo(); console.log('获取到的用户列表:', returned); // 这里可以正常使用返回的数组 } catch (err) { console.error('查询Cassandra出错:', err); } } // 调用函数 getRankedUsers();
方式2:使用.then()链式调用
foo() .then(returned => { console.log('获取到的用户列表:', returned); }) .catch(err => { console.error('查询Cassandra出错:', err); });
关键说明
- Promise的作用就是把异步的事件逻辑转换成可以等待的对象,确保我们在数据完全收集完成后才拿到结果。
- 一定要处理
error事件,否则如果查询出错,Promise会一直处于pending状态,导致代码卡住。 - 原来的
resultArray现在通过Promise的resolve传递到外部,不再受回调作用域的限制。
内容的提问来源于stack exchange,提问作者stark0323
相关产品推荐
相关产品推荐

