切换至request-promise.get后出现responseText未定义及JSON.parse问题求助
解决TypeError: Cannot read property 'responseText' of undefined的问题
让我来帮你梳理一下问题所在,其实是几个细节冲突和使用误区凑到一起导致的错误:
1. 核心问题:命名冲突覆盖了request-promise包
你犯了一个典型的变量命名冲突错误:
- 你先导入了
request-promise包到requestPromise变量 - 然后又自己定义了一个同名的
requestPromise函数,直接把官方包的对象给覆盖了
这导致你调用requestPromise.get()的时候,实际调用的是你自己写的那个简陋的XHR封装函数,而不是官方包提供的get方法——你自己的函数根本没有get属性,自然会引发后续的响应读取错误。
2. 响应处理的误区
官方的request-promise包有自己的响应格式规则:
- 当你设置
json: true时,包会自动把API返回的JSON响应解析成JavaScript对象,不需要再手动调用JSON.parse - 如果设置了
resolveWithFullResponse: true,完整的响应对象里,解析后的JSON数据在r1.body属性中,而不是r1.target.responseText(这是原生XHR事件的属性,和request-promise无关)
3. 数据库保存的变量错误
你的saveToDatabase函数里,插入MongoDB的对象写的是Volume: 'BTCdata',这里的单引号会把它变成字符串,而不是传递变量值,应该改成Volume: BTCdata。
修复后的完整代码
// 把导入的包重命名,避免和自定义函数冲突(或者直接删掉自定义的requestPromise函数) const rp = require('request-promise'); const { MongoClient } = require('mongodb'); const schedule = require('node-schedule'); // 这里不需要XMLHttpRequest了,因为用request-promise处理请求 // var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; const saveToDatabase = function(BTCdata) { const url = 'mongodb+srv://username:password@cluster0-1kunr.mongodb.net/<dbname>?retryWrites=true&w=majority'; MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }, (err, db) => { if (err) throw err; const dbo = db.db('Crypto'); // 去掉BTCdata的单引号,传递变量值 const myobj = { Name: 'BTC', Volume: BTCdata }; dbo.collection('Crypto-Values').insertOne(myobj, (error, res) => { if (error) throw error; console.log('1 document inserted'); db.close(); }); }); }; // 删掉自己定义的requestPromise函数,用官方包的rp.get const j = schedule.scheduleJob('* * * * * *', () => { rp.get({ uri: 'http://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?CMC_PRO_API_KEY=API-KEY-HERE', json: true, // 注意这里要加逗号,修复语法错误 resolveWithFullResponse: true }).then(r1 => { // 直接用r1.body,不需要JSON.parse const BTCdata = r1.body.data.find(d => d.symbol === 'BTC').quote.USD.volume_24h; console.log(BTCdata); saveToDatabase(BTCdata); }).catch(err => { console.log(err); }); });
额外提示
- 建议把API密钥放到环境变量里,不要直接写在代码中,避免泄露
- 可以考虑用async/await替代
.then/.catch,让异步代码更易读 - Node.js的MongoDB驱动现在推荐用async/await的方式连接,回调函数的方式可以逐步替换
内容的提问来源于stack exchange,提问作者Hexycode
相关产品推荐
相关产品推荐

