为何调用MobX Store中私有成员setUser时提示超出作用域?
问题原因与解决办法
核心问题
你调用AWS SDK的listGroups和listUsersInGroup时用了普通function作为回调,此时回调内部的this已经不再指向你的MobX Store实例,自然找不到setUser方法。而另一个能正常运行的loadSubmittals用了async/await处理异步,forEach里的箭头函数会保留外层作用域的this指向,所以能正常调用setSubmittal。
三种解决办法
方法1:把回调改成箭头函数
箭头函数不会绑定自己的this,会继承外层作用域的this,直接替换所有普通function回调即可:
loadUsersFromPoolGroups = () => { this.loadingInitial = true; try { const congitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider(); const USER_POOL_ID = 'us-east-2_kWOEamV6i'; const params = { UserPoolId: USER_POOL_ID } congitoidentityserviceprovider.listGroups(params, (err, data) => { if (err) console.log(err, err.stack); else { data.Groups.forEach(group => { const params = { GroupName: group.GroupName, UserPoolId: USER_POOL_ID } congitoidentityserviceprovider.listUsersInGroup(params, (err1, data1) => { if (err1) console.log(err1, err1.stack); else { data1.Users.forEach((user) => { this.setUser(user); }) } }) }) } }); } catch (error) { console.log('error loading users from pool groups', error) } }
方法2:提前保存Store的this引用
在回调外部把this存成变量(比如self),回调里用这个变量代替this:
loadUsersFromPoolGroups = () => { this.loadingInitial = true; const self = this; try { const congitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider(); const USER_POOL_ID = 'us-east-2_kWOEamV6i'; const params = { UserPoolId: USER_POOL_ID } congitoidentityserviceprovider.listGroups(params, function(err, data) { if (err) console.log(err, err.stack); else { data.Groups.forEach(group => { const params = { GroupName: group.GroupName, UserPoolId: USER_POOL_ID } congitoidentityserviceprovider.listUsersInGroup(params, function(err1, data1) { if (err1) console.log(err1, err1.stack); else { data1.Users.forEach((user) => { self.setUser(user); }) } }) }) } }); } catch (error) { console.log('error loading users from pool groups', error) } }
方法3:Promise化AWS SDK方法,用async/await简化代码
AWS SDK支持把回调式方法转换成Promise,这样可以和你另一个Store一样用async/await,代码更简洁,也不会有this指向问题:
loadUsersFromPoolGroups = async () => { this.loadingInitial = true; try { const congitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider(); const USER_POOL_ID = 'us-east-2_kWOEamV6i'; const params = { UserPoolId: USER_POOL_ID } const data = await congitoidentityserviceprovider.listGroups(params).promise(); for (const group of data.Groups) { const groupParams = { GroupName: group.GroupName, UserPoolId: USER_POOL_ID } const data1 = await congitoidentityserviceprovider.listUsersInGroup(groupParams).promise(); data1.Users.forEach((user) => { this.setUser(user); }) } } catch (error) { console.log('error loading users from pool groups', error) } finally { this.loadingInitial = false; } }
内容的提问来源于stack exchange,提问作者jswift
相关产品推荐
相关产品推荐

