Node.js中request调用Firebase报错TypeError: then不是函数
解决Node.js中request回调无法用.then()及全局作用域获取异步值的问题
首先得明确你遇到问题的根源:你当前用的request模块是基于回调函数设计的,它执行后返回的并不是Promise对象,所以直接调用.then()方法自然会触发TypeError: request(...).then is not a function这个错误。另外异步操作的特性也导致你没法直接在全局作用域同步拿到返回值——因为异步代码会在同步代码执行完后才运行。
下面给你几个可行的解决方案:
方案一:改用支持Promise的request衍生库
最省心的方式是用request-promise(或者request-promise-native,基于原生Promise),它是request的Promise化封装版本。
- 先安装依赖:
npm install request-promise
- 修改你的代码:
const rp = require('request-promise'); rp(options) .then(body => { const key = body.notification_key; console.log('my key is : ' + key); // 这里可以把key赋值给全局变量,或者直接在这里处理后续逻辑 global.notificationKey = key; // 全局变量赋值示例 }) .catch(error => { console.error('请求出错啦:', error); });
方案二:手动封装Promise
如果你不想额外安装依赖,可以自己把回调式的request包装成Promise:
const request = require('request'); // 封装一个返回Promise的请求函数 function makeRequest(options) { return new Promise((resolve, reject) => { request(options, (error, response, body) => { if (error) { reject(error); // 请求失败时抛出错误 } else { resolve(body); // 请求成功时返回body } }); }); } // 使用封装后的函数 makeRequest(options) .then(body => { const key = body.notification_key; console.log('my key is : ' + key); // 处理全局变量或后续逻辑 }) .catch(error => { console.error('请求失败:', error); });
方案三:用async/await简化异步代码
基于上面的Promise封装,你可以用async/await让代码看起来更像同步逻辑:
const request = require('request'); function makeRequest(options) { return new Promise((resolve, reject) => { request(options, (error, response, body) => { if (error) { reject(error); } else { resolve(body); } }); }); } // 定义一个async函数 async function getNotificationKey() { try { const body = await makeRequest(options); const key = body.notification_key; console.log('my key is : ' + key); // 赋值给全局变量 global.notificationKey = key; return key; } catch (error) { console.error('请求出错:', error); throw error; // 可以选择抛出错误让上层处理 } } // 调用函数 getNotificationKey();
关于全局变量取值的注意点
一定要记住:异步操作是非阻塞的,所以你不能在同步代码里直接去取刚赋值的全局变量,比如下面的写法是错误的:
let key; getNotificationKey().then(() => {}); console.log(key); // 这里会输出undefined,因为异步代码还没执行完
所有需要使用key的逻辑,都必须放在.then()回调里,或者await之后的代码块中。
内容的提问来源于stack exchange,提问作者rituparna
相关产品推荐
相关产品推荐

