NodeJS升级SOAP模块(1.0.0)后出现req.then is not a function错误排查
排查soap模块1.0.0升级后
req.then is not a function错误 核心问题分析
升级soap模块到1.0.0后出现req.then is not a function错误,根源在于soap 1.x版本内部对请求函数的Promise化要求:旧版soap模块兼容回调风格的request库,但1.x版本会尝试对传入的request调用.then()方法,而你当前使用的request.defaults()返回的对象是回调风格,不支持Promise链式调用,因此触发错误。
排查步骤
确认request库版本与soap的兼容性
soap 1.0.0要求请求函数返回Promise,而传统的request@2.x默认是回调风格,不自带Promise支持。执行以下命令查看当前request版本:npm list request验证request选项的调用方式
检查soap_client_options中的request属性:soap模块会将请求逻辑委托给这个函数,1.x版本期望它返回一个Promise对象,而request.defaults()返回的是一个回调风格的函数,无法满足这个要求。
修复方案
方案1:替换为支持Promise的request库
改用request-promise-native(轻量级,基于原生Promise),它的API与request兼容,但默认返回Promise:
- 安装依赖:
npm install request-promise-native --save - 修改代码:
const request = require('request-promise-native'); // 替换原request引入 const url = 'https://example.com/wsi/service.php?wsdl'; let args = { username: 'username', authKey: 'auth_key', sender: '', recipient: req.user.phone, message: '', scheduleDate: '', validity: '', callbackUrl: '' }; // 保持defaults配置不变 let request_with_defaults = request.defaults({ 'proxy': 'proxy', 'timeout': 5000, 'connection': 'keep-alive' }); let soap_client_options = { 'request': request_with_defaults }; args.message = generateSMSCode(req, codeTime); args.recipient = req.user.phone; // 修正变量引用问题,原代码中phone未定义 // 改用soap的Promise风格API(更符合1.x版本设计) soap.createClient(url, soap_client_options) .then(client => client.sendSmsAuthKey(args)) .then(result => { console.log(currentDateTime.getCurrentDate() + " - Code Sent at " + codeDateTime + "!"); res.redirect('/auth/validate'); }) .catch(err => { console.log(currentDateTime.getCurrentDate() + " - ERROR!"); console.log(err); });
方案2:包装传统request为Promise风格
如果不想替换库,可以手动包装request函数,让它返回Promise:
const request = require('request'); const url = 'https://example.com/wsi/service.php?wsdl'; // 包装request为Promise风格 function promisifiedRequest(options) { return new Promise((resolve, reject) => { request(options, (err, response, body) => { if (err) return reject(err); resolve({ response, body }); }); }); } let args = { username: 'username', authKey: 'auth_key', sender: '', recipient: req.user.phone, message: '', scheduleDate: '', validity: '', callbackUrl: '' }; // 用包装后的函数替代request.defaults返回的对象 let soap_client_options = { 'request': promisifiedRequest }; args.message = generateSMSCode(req, codeTime); args.recipient = req.user.phone; // 原回调风格代码可继续使用 soap.createClient(url, soap_client_options, function(err, client) { if (err) { console.log(currentDateTime.getCurrentDate() + " - ERROR!"); console.log(err); return; } client.sendSmsAuthKey(args, function(err, result) { if (err) { console.log(currentDateTime.getCurrentDate() + " - ERROR!"); console.log(err); } else { console.log(currentDateTime.getCurrentDate() + " - Code Sent at " + codeDateTime + "!"); res.redirect('/auth/validate'); } }); });
额外代码优化提示
- 原代码中
args.recipient = phone;的phone变量未定义,建议修正为req.user.phone或确保变量已正确声明。 - 升级后建议逐步迁移到soap模块的Promise风格API,回调风格虽然兼容,但Promise更符合Node.js现代异步编程规范。
内容的提问来源于stack exchange,提问作者daydr3am3r
相关产品推荐
相关产品推荐

