从 AWS SQS 获取数据并等待呈现 ReactJs
Fetching data from AWS SQS and wait to render ReactJs
所以我们遇到了一个问题,我们向 SQS 发送请求,然后在接收消息时 returns 没有数据。
为了尝试解决这个问题,我们加入了一个 while 循环以延长轮询时间;然而,这真的行不通,因为我们不能在轮询之间休眠,而且似乎它们都是异步发生的。
我这么说是因为如果确实返回了值(大约有 50% 的时间发生),它将重新渲染下一个屏幕,次数与剩余的上限一样多,并且轮询永远不会设置为 false。有人可以帮助我们吗!
render() {
return (
<Navigator
renderScene={this.renderScene.bind(this)}
navigator={this.props.navigator}
navigationBar={
<Navigator.NavigationBar style={{backgroundColor: 'transparent'}}
routeMapper={NavigationBarRouteMapper} />
} />
);
}
renderScene() {
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" hidden={true}/>
<View style={styles.topContainer}>
<View style={styles.bannerContainer}>
<View style={{flexDirection: 'column', flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Image style={styles.mark} source={require('./yb.png')} />
</View>
</View>
<View style={styles.credentialContainer}>
<View style={styles.inputContainer}>
<Icon style={styles.inputPassword} name="person" size={28} color="#FFCD00" />
<View style={{flexDirection: 'row', flex: 1, marginLeft: 2, marginRight: 2, borderBottomColor: '#e0e0e0', borderBottomWidth: 2}}>
<TextInput
style={styles.input}
placeholder="Username"
autoCorrect={false}
placeholderTextColor="#e0e0e0"
onChangeText={(text) => this.setState({username: text})}
value={this.state.username}>
</TextInput>
</View>
</View>
<View style={styles.inputContainer}>
<Icon style={styles.inputPassword} name="lock" size={28} color="#FFCD00" />
<View style={{flexDirection: 'row', flex: 1, marginLeft: 2, marginRight: 2, borderBottomColor: '#e0e0e0', borderBottomWidth: 2}}>
<TextInput
style={styles.input}
placeholder="Password"
autoCorrect={false}
secureTextEntry={true}
placeholderTextColor="#e0e0e0"
onChangeText={(text) => this.setState({password: text})}
value={this.state.password}>
</TextInput>
</View>
</View>
<TouchableOpacity style={styles.forgotContainer}>
<Text style={{color: '#e0e0e0'}}>Forgot Password</Text>
</TouchableOpacity>
</View>
</View>
<TouchableHighlight
underlayColor="#D6AB00"
onPress={this.login}
style={styles.signInButtonContainer}>
<Text style={styles.signInText}>Sign In</Text>
</TouchableHighlight>
</View>
);
}
login() {
var polling = true;
if(this.state.username.length == 0){
Alert.alert("Error","No email entered");
}
else if(this.state.password.length == 0){
Alert.alert("Error","No password entered");
}
else
{
info.username = this.state.username;
info.password = this.state.password;
AWS.sendMessage('****',JSON.stringify(info), (error,result) =>{
if(error != null) console.log("Error Occured Attempting to Send A Message")
else {
var cap=0;
while(cap <= 30 && polling){
cap = cap+1;
AWS.receiveMessages('****'+info.username, (error, result) =>{
if(error != null) console.log("Error");
else{
if(result){
try{
polling = false;
if(result[0] == "[]")
{
console.log(result[0]);
console.log(typeof result[0]);
Alert.alert("Error","Username/Password Incorrect");
}
else
{
console.log(result[0]);
console.log(typeof result[0]);
var temp = JSON.parse(result[0]);
this.props.navigator.replace({
id: 'MapIOS',
data: {
username: info.username,
ofAge: temp[0].ofAge,
uid: temp[0].u_ID
},
});
}
}
catch(e){
console.log(e);
}
}
AWS.deleteMessage('***'+info.username, result[1], (error) => {
if(error != null) console.log("Error");
});
}
});
}
return
}
});
}
}
};
使用 SQS 时需要注意的一些重要事实:
- SQS 不是 "first in, first out"。消息的接收顺序可能与它们放入队列的顺序不同。因此,如果您添加消息“1”然后“2”,您可能会收到“2”然后“1”。
- 即使消息在队列中,您在调用
ReceiveMessage
时也可能收不到消息。
- 您可能会多次收到同一条消息。例如,如果您将消息“1”添加到队列中,您稍后可能会返回“1”然后再次返回“1”。所以你需要保证消息处理是幂等的和重复安全的。
以上都是因为SQS是分布式冗余的。它保证您会收到消息,但不保证消息的顺序或接收次数。
更新:
这是我最初的回答,但我认为这不是代码的主要问题。我把它留在这里,因为我认为它仍然是有价值的信息。
问题是您正在循环调用 AWS.ReceiveMessage
。
当您调用 AWS.ReceiveMessage
时,调用是异步的。意思是,它将立即 return 。它不会等待您的回调被调用。因此,在调用任何回调之前,您的循环可能会耗尽。
尝试从回调函数设置 polling
变量并不是 "protect" 回调的安全方法。
您需要重组函数,以便在第一个 AWS.ReceiveMessage
.
调用回调之前不会发生第二个 AWS.ReceiveMessage
一般来说,不要循环。
所以我们遇到了一个问题,我们向 SQS 发送请求,然后在接收消息时 returns 没有数据。
为了尝试解决这个问题,我们加入了一个 while 循环以延长轮询时间;然而,这真的行不通,因为我们不能在轮询之间休眠,而且似乎它们都是异步发生的。
我这么说是因为如果确实返回了值(大约有 50% 的时间发生),它将重新渲染下一个屏幕,次数与剩余的上限一样多,并且轮询永远不会设置为 false。有人可以帮助我们吗!
render() {
return (
<Navigator
renderScene={this.renderScene.bind(this)}
navigator={this.props.navigator}
navigationBar={
<Navigator.NavigationBar style={{backgroundColor: 'transparent'}}
routeMapper={NavigationBarRouteMapper} />
} />
);
}
renderScene() {
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" hidden={true}/>
<View style={styles.topContainer}>
<View style={styles.bannerContainer}>
<View style={{flexDirection: 'column', flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Image style={styles.mark} source={require('./yb.png')} />
</View>
</View>
<View style={styles.credentialContainer}>
<View style={styles.inputContainer}>
<Icon style={styles.inputPassword} name="person" size={28} color="#FFCD00" />
<View style={{flexDirection: 'row', flex: 1, marginLeft: 2, marginRight: 2, borderBottomColor: '#e0e0e0', borderBottomWidth: 2}}>
<TextInput
style={styles.input}
placeholder="Username"
autoCorrect={false}
placeholderTextColor="#e0e0e0"
onChangeText={(text) => this.setState({username: text})}
value={this.state.username}>
</TextInput>
</View>
</View>
<View style={styles.inputContainer}>
<Icon style={styles.inputPassword} name="lock" size={28} color="#FFCD00" />
<View style={{flexDirection: 'row', flex: 1, marginLeft: 2, marginRight: 2, borderBottomColor: '#e0e0e0', borderBottomWidth: 2}}>
<TextInput
style={styles.input}
placeholder="Password"
autoCorrect={false}
secureTextEntry={true}
placeholderTextColor="#e0e0e0"
onChangeText={(text) => this.setState({password: text})}
value={this.state.password}>
</TextInput>
</View>
</View>
<TouchableOpacity style={styles.forgotContainer}>
<Text style={{color: '#e0e0e0'}}>Forgot Password</Text>
</TouchableOpacity>
</View>
</View>
<TouchableHighlight
underlayColor="#D6AB00"
onPress={this.login}
style={styles.signInButtonContainer}>
<Text style={styles.signInText}>Sign In</Text>
</TouchableHighlight>
</View>
);
}
login() {
var polling = true;
if(this.state.username.length == 0){
Alert.alert("Error","No email entered");
}
else if(this.state.password.length == 0){
Alert.alert("Error","No password entered");
}
else
{
info.username = this.state.username;
info.password = this.state.password;
AWS.sendMessage('****',JSON.stringify(info), (error,result) =>{
if(error != null) console.log("Error Occured Attempting to Send A Message")
else {
var cap=0;
while(cap <= 30 && polling){
cap = cap+1;
AWS.receiveMessages('****'+info.username, (error, result) =>{
if(error != null) console.log("Error");
else{
if(result){
try{
polling = false;
if(result[0] == "[]")
{
console.log(result[0]);
console.log(typeof result[0]);
Alert.alert("Error","Username/Password Incorrect");
}
else
{
console.log(result[0]);
console.log(typeof result[0]);
var temp = JSON.parse(result[0]);
this.props.navigator.replace({
id: 'MapIOS',
data: {
username: info.username,
ofAge: temp[0].ofAge,
uid: temp[0].u_ID
},
});
}
}
catch(e){
console.log(e);
}
}
AWS.deleteMessage('***'+info.username, result[1], (error) => {
if(error != null) console.log("Error");
});
}
});
}
return
}
});
}
}
};
使用 SQS 时需要注意的一些重要事实:
- SQS 不是 "first in, first out"。消息的接收顺序可能与它们放入队列的顺序不同。因此,如果您添加消息“1”然后“2”,您可能会收到“2”然后“1”。
- 即使消息在队列中,您在调用
ReceiveMessage
时也可能收不到消息。 - 您可能会多次收到同一条消息。例如,如果您将消息“1”添加到队列中,您稍后可能会返回“1”然后再次返回“1”。所以你需要保证消息处理是幂等的和重复安全的。
以上都是因为SQS是分布式冗余的。它保证您会收到消息,但不保证消息的顺序或接收次数。
更新:
这是我最初的回答,但我认为这不是代码的主要问题。我把它留在这里,因为我认为它仍然是有价值的信息。
问题是您正在循环调用 AWS.ReceiveMessage
。
当您调用 AWS.ReceiveMessage
时,调用是异步的。意思是,它将立即 return 。它不会等待您的回调被调用。因此,在调用任何回调之前,您的循环可能会耗尽。
尝试从回调函数设置 polling
变量并不是 "protect" 回调的安全方法。
您需要重组函数,以便在第一个 AWS.ReceiveMessage
.
AWS.ReceiveMessage
一般来说,不要循环。