Promise异步流程异常:旧XP获取与更新函数执行顺序及NaN问题
问题分析与修复方案
你的代码核心问题出在异步时序混乱和变量初始化时机错误,导致要么拿不到旧XP值,要么计算出NaN,具体问题点和修复方案如下:
核心问题点
new_xp和updated_XP在代码加载阶段就执行了,这时候old_Xp的异步请求还没完成,oldxpuser仍是undefined,所以new_xp = undefined +50会变成NaN。- 重复调用
old_Xp():第一次调用没传UID参数(old_Xp())会触发请求错误,第二次单独调用old_Xp(8)但未关联后续update_Xp,导致两个异步请求并行,执行顺序完全不可控。 - 依赖全局变量
oldxpuser传递异步数据,极易出现时序问题,应该用Promise返回值传递数据,避免全局变量污染。
修复后的完整代码
// 获取用户旧XP的函数,移除全局变量,通过Promise直接返回结果 function old_Xp(UID) { return new Promise(function (resolve, reject) { redmine.users(UID, function(err, data) { if (err) { reject(err); return; } // 用find快速定位目标用户 const targetUser = data.users.find(user => user.id === UID); if (!targetUser) { reject(new Error(`用户ID ${UID} 不存在`)); return; } const oldxpuser = parseInt(targetUser.custom_fields[0].value); console.log("old xp: " + oldxpuser); resolve(oldxpuser); }); }); } // 更新XP的函数,改为接收新XP值作为参数 function update_Xp(UID, newXp) { return new Promise(function(resolve, reject) { const updated_XP = { user: { custom_fields: [{ id: 1, value: newXp }] } }; redmine.update_user(UID, updated_XP, function(err, data) { if (err) { console.log(err); reject(err); return; } console.log('Updated !!'); resolve(data); }); }); } // 正确的异步执行流程:先获取旧XP,计算新值,再执行更新 old_Xp(8) .then(oldxpuser => { const new_xp = oldxpuser + 50; console.log(new_xp); return update_Xp(8, new_xp); }) .then(() => { console.log("ME: your promise has been resolved"); check_XP(); // 确保更新完成后再执行检查 }) .catch(function(error) { console.log("Error occured ERROR:" + error); });
关键修复说明
- 移除全局变量:
old_Xp通过resolve直接返回旧XP值,在then回调中接收,彻底避免全局变量的时序问题。 - 固定异步执行顺序:把
new_xp计算、update_Xp调用都放到old_Xp的then回调内,确保只有拿到旧XP后才执行后续操作。 - 改造
update_Xp:让它接收新XP值作为参数,内部生成更新对象,保证每次更新用的都是最新计算的值。 - 统一异步流程:只调用一次
old_Xp(8),通过Promise链式调用严格控制执行顺序,同时将check_XP()放到更新完成后的回调中,确保检查的是最新数据。 - 优化用户查找逻辑:用
Array.find()替代for循环,代码更简洁,同时新增用户不存在的错误处理分支。
内容的提问来源于stack exchange,提问作者Rishabh Rawat
相关产品推荐
相关产品推荐

