从 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 时需要注意的一些重要事实:

  1. SQS 不是 "first in, first out"。消息的接收顺序可能与它们放入队列的顺序不同。因此,如果您添加消息“1”然后“2”,您可能会收到“2”然后“1”。
  2. 即使消息在队列中,您在调用 ReceiveMessage 时也可能收不到消息。
  3. 您可能会多次收到同一条消息。例如,如果您将消息“1”添加到队列中,您稍后可能会返回“1”然后再次返回“1”。所以你需要保证消息处理是幂等的和重复安全的。

以上都是因为SQS是分布式冗余的。它保证您会收到消息,但不保证消息的顺序或接收次数。

更新:

这是我最初的回答,但我认为这不是代码的主要问题。我把它留在这里,因为我认为它仍然是有价值的信息。

问题是您正在循环调用 AWS.ReceiveMessage

当您调用 AWS.ReceiveMessage 时,调用是异步的。意思是,它将立即 return 。它不会等待您的回调被调用。因此,在调用任何回调之前,您的循环可能会耗尽。

尝试从回调函数设置 polling 变量并不是 "protect" 回调的安全方法。

您需要重组函数,以便在第一个 AWS.ReceiveMessage.

调用回调之前不会发生第二个 AWS.ReceiveMessage

一般来说,不要循环。