OGeek|极客世界-中国程序员成长平台

标题: javascript - 在 React-Native 中处理服务调用的通用基类方法 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 18:54
标题: javascript - 在 React-Native 中处理服务调用的通用基类方法

目标:
通过我的 Network 类调用 Web 服务的通用方法显示微调器,同时在完成后将其删除,然后通过显示警报最终处理错误,否则将响应发送回我的调用类。

我做了什么: 我已经编写了以下方法,即在我的基类中,所有类都将具有此方法。

问题: 由于调用了 setState 来更新屏幕,因此任何警报(错误/成功)都会出现片刻,然后最后一个屏幕出现在前面,并且所有事情都卡住了,因为警报在屏幕后面。

要求: 谁能指出我在做什么错误或如何处理这个问题的任何概念。

import React, { Component } from 'react'
import { View } from 'react-native'
import Network from './Network';

export default class BaseClass extends Component {
   constructor() {
      super()
      this.state = {
         spinner:false,
         response:''
      }
   }

  onPress(data){
      this.setState({ spinner: true })

      var net = new Network();
      net.makeCall(data,function(context,err,res){
      context.setState({ spinner: false })

      if(err!= null){
       alert('error')
      }
      else{
         alert('sccess')
      }
      )
     }
}

第二种方法 我采用了第二种方法,但在这里得到了相同的结果。

import React, { Component } from 'react'
    import { View } from 'react-native'
    import Network from './Network';

    export default class BaseClass extends Component {
       constructor() {
          super()
          this.state = {
             spinner:false,
             response:''
          }
       }

      onPress(data){
          this.setState({ spinner: true })

          var net = new Network();
          net.makeCall(data,function(context,err,res){
          context.setState({ spinner: false })

          if(err!= null){
           context.setState({ response: err })
          }
          else{
             context.setState({ response: data })
          }
          )
       }

    componentDidUpdate(){
    alert(this.state.response)
    }
    }



Best Answer-推荐答案


我目前的工作类,少数类是自定义类,如 Screens、SessionManager、SessionTimer、Constants

"use strict";
import React, {Component} from 'react';
import Spinner from 'react-native-loading-spinner-overlay';
import Pinch from 'react-native-pinch';
import Config from './Config'
import {SessionManager} from './utilities/SessionManager';
import Constants from './utilities/Constants'
import {Platform, Alert} from 'react-native';
import {Screens} from './navigation/Screens'
import SessionTimer from './utilities/SessionTimer';
import IMEI from './utilities/IMEI'
// Check Device Info
var DeviceInfo = require('react-native-device-info');

//import Spinner from  'react-native-spinkit'

/*
 this class will be used to communicate with
 server and getting url params from the calling class,
 handles the server error if there is no error it will
 return the repsonse to the calling class
 */
export class WebServiceCallManager extends Component {

    constructor(props) {
        super(props);
        this.state = {
            visible: this.props.visible,
            size: 100,
        }
    }

    callWebService(requestAction, subAction, bodyParams, responseHandler, optionalErrHandler) {
        this.setState({visible: true});//Starting the Processing indicator
        let imei = null;
        if (Platform.OS === 'android') {
            imei = SessionManager.getSessionValue("IMEI");
        }

        var params = {
            "Header": {
                "AppVersion": DeviceInfo.getVersion(),
                //"IMEI":imei,
                //"DEVICE_MAKE" : (Platform.OS === 'android') ?  "AN": (Platform.OS === 'ios') ? "IP" : "OT",
                "Channel": (Platform.OS === 'android') ? 'MOBILE_ANDROID' : (Platform.OS === 'ios') ? "MOBILE_IOS" : null,
                // DeviceInfo.getManufacturer()
                //    "Channel"eviceInfo.getManufacturer(),
                //"DeviceId": DeviceInfo.getUniqueID(),
                //  "NetworkType": "MOBILE DATA 3G",
                "RequestAction": requestAction,
                "SubAction": subAction,
                "Token": SessionManager.getSessionValue(Constants.TOKEN),
                //  "Operator": "ZONG",
                "CSRF": SessionManager.getSessionValue(Constants.CSRF),
                //"OS": DeviceInfo.getSystemVersion(),
                "DeviceInformation": {
                    "IMEI": imei,
                    "Manufacturer": DeviceInfo.getManufacturer(),
                    "Model": DeviceInfo.getModel(),
                    "DeviceId": DeviceInfo.getUniqueID(),
                    "DeviceMake": (Platform.OS === 'android') ? "AN" : (Platform.OS === 'ios') ? "IP" : "OT",
                    "OS": DeviceInfo.getSystemVersion(),
                }

            },
            "Body": {
                "Transaction": bodyParams
            }
        };

        var url = Config.IP;

        if (url.startsWith('https')) {
            this._httpsCalling(url, params, responseHandler, optionalErrHandler);
        } else {
            this._httpCalling(url, params, responseHandler, optionalErrHandler);
        }
    }

    _httpsCalling(url, params, responseHandler) {
        Pinch.fetch(url,
            {
                method: "OST",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(params),
                sslPinning: {
                    cert: 'prodcer'
                }
            })
            .then((responseResult) => {
                this.setState({visible: false});// removing the Processing symbol
                var result = JSON.parse(responseResult.bodyString);
                var strResult = JSON.stringify(result);
                if (responseResult.status == '0') {
                    responseHandler(strResult);
                }
                else {
                    responseHandler(strResult);

                }
            }).catch((err) => {
            this.setState({visible: false});// removing the Processing symbol
            responseHandler(err.message + '');
        })
            .done();
    }

    _httpCalling(url, params, responseHandler, optionalErrHandler) {
        fetch(url,
            {
                method: "OST",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(params)

            })
            .then((resType) => resType.json())
            .then((responseResult) => {
                let timer = new SessionTimer();
                timer.resetSessionTimer(0);
                this.setState({visible: false});// removing the Processing symbol
                SessionManager.setSessionValue(Constants.TOKEN, responseResult.Header.Cookie);
                SessionManager.setSessionValue(Constants.CSRF, responseResult.Header.CSRF);
                if (responseResult.Header.ResponseCode == '0') {

                    responseHandler(responseResult);
                }
                else {
                    if (optionalErrHandler !== undefined) {
                        optionalErrHandler(responseResult.Header);
                    }
                    this.errorHandler(responseResult.Header);
                    // responseHandler(null ,responseResult.Header.ResponseMessage);

                }
            }).catch((err) => {

            var error = {ResponseMessage: err.message};

            if (optionalErrHandler !== undefined) {
                optionalErrHandler(error);
            }

            this.errorHandler(error);
        })
            .done();
    }

    errorHandler(errorData) {

        this.setState({visible: false});// removing the Processing symbol

        let msg = errorData.ResponseMessage;
        let errorCode = errorData.ResponseCode;

        if (errorCode == 111) {
            setTimeout(
                () => {
                    Alert.alert('Respose Error ' +
                        msg,
                        '',
                        [
                            {
                                text: 'OK', onPress: () => {
                                this.props.nav.popToRoute(Screens.LoginScreen)
                            }
                            },
                        ],
                        {cancelable: false}
                    )
                },
                100
            );
        }
        else {

            setTimeout(
                () => {
                    alert(msg)
                },
                100
            );
        }
    }

    render() {
        return <Spinner visible={this.state.visible} itemProp='size:100'/>
    }
}

2019 年 9 月 16 日编辑:

在这里我添加了另一个类,我使用了上面定义的网络类,实际上它是 React 世界中的一个组件,所以在渲染方法中我们添加了这个组件并获得了我们调用方法的那个组件的引用callWebService()

import React, { Component } from 'react';

import {  StyleSheet, Text, View, Button,Switch, Alert, Image, TouchableHighlight, Dimensions, Platform,AppState } from 'react-native';
import Constants from '.././utilities/Constants'
import {Screens} from '.././navigation/Screens'
import {ScreenClass} from '.././navigation/Screens';
import TextInputCustom from '.././components/TextInputCustom';
import {SessionManager} from '../utilities/SessionManager';
import {WebServiceCallManager} from '.././WebServiceCallManager';
import {NavigationManager} from '.././navigation/NavigationManager';
import Fingerprint from '.././fingerprint/FingerprintAndroid';


const dismissKeyboard = require('dismissKeyboard');
const { width, height } = Dimensions.get("window");
let opacity = 1;
// source address of login background image
const loginBackgroundViewImg = require('.././assets/login_box.png');
const biometricImage = require('.././assets/biometric_icon.png');

var langs = new Constants(); // language localization


/* Login View for displaying TextInputs(username, passwords),
   Buttons (Login, Register) and Labels (Terms & condition , forget password)
*/

export class LoginContainer extends Component {
     constructor(props){
          super(props);
          this.state = {
            username: '' , // user33
            password: '', // Awaqas@2
            emptyInputFields : '',
            falseSwitchIsOn : true,
            phase: 'normal',
            message: '',
            cancelled: false
          }
     }



     componentDidMount() {
      //  Fingerprint.saveCredentials("user33","Awaqas@2",()=>{
      //   this.setState({
      //       phase: 'saved',
      //       message: ''
      //   });
      //  },()=>{});

            this.authenticate();

             AppState.addEventListener("change", async(state) => {
                 try {
                     if(state === "active" && await Fingerprint.isAuthenticationCanceled()) {
                         this.authenticate()
                     }
                 }
                 catch(z) {
                     console.error(z)
                 }
             })
         }

         async componentWillUnmount() {
             try {
                 if(!Fingerprint.isAuthenticationCanceled()) {
                     //stop listening to authentication.
                     await Fingerprint.cancelAuthentication();
                 }
             } catch(z) {
                 console.error(z);
             }
         }

         async authenticate() {

             try {
                 // do sanity checks before starting authentication flow.
                 // HIGHLY recommended in real life usage. see more on why you should do this in the readme.md
                 const hardware = await Fingerprint.isHardwareDetected();
                 const permission = await Fingerprint.hasPermission();
                 const enrolled = await Fingerprint.hasEnrolledFingerprints();

                 if (!hardware || !permission || !enrolled) {
                     let message = !enrolled ? 'No fingerprints registered.' : !hardware ? 'This device doesn\'t support fingerprint scanning.' : 'App has no permission.'
                     this.setState({
                         phase: 'fail',
                         message
                     });
                     return;
                 }

                  await Fingerprint.authenticate(warning => {
                     this.setState({
                         phase: 'warn',
                         message: warning.message
                     })
                 });

                 // if we got this far, it means the authentication succeeded.
                 this.setState({
                     phase: 'success',
                     message: ''
                 });

                 // in real life, we'd probably do something here (process the payment, unlock the vault, whatever)
                 // but this is a demo. so restart authentication.
                // setTimeout(() => this.authenticate(), 3000);

             } catch (error) {
                 if(error.code == Fingerprint.FINGERPRINT_ERROR_CANCELED) {
                     // we don't show this error to the user.
                     // we will check if the auth was cancelled & restart the flow when the appstate becomes active again.
                     return;
                 }
                 this.setState({
                     phase: 'fail',
                     message: error.message
                 })
             }
         }

      buttonsHandler(type){
          switch (type) {
               case 'forgotpassword':
                    this.props.navigation.push(Screens.ForgotPasswordScreen);
                    break;
               case 'forgotuserid':
                this.props.navigation.push(Screens.ForgotUserIDScreen);
                    break;
               case 'unlockprofile':
                this.props.navigation.push(Screens.UnlockProfileScreen);
                    break;
              case 'register':
                  dismissKeyboard();
                  this.props.navigation.push(Screens.RegistrationWelcomeScreen);
                  break;
               case 'login':
                    this.loginWebServiceCall();
                    break;
               default:
                     alert(type + ' is pressed');

          }
    }


    // this will be called when user hit login button

    loginWebServiceCall()
    {

         if(this.state.username.length === 0 &&  this.state.password.length === 0){
            this.setState({emptyInputFields:langs.strings.login_userid_password_empty});
            this.userName.textFocus();
         }
         else if (this.state.username.length === 0 ) {
           this.setState({emptyInputFields:langs.strings.login_userid_empty});
           this.userName.textFocus();
         }
         else if ( this.state.password.length === 0) {
           this.setState({emptyInputFields:langs.strings.login_password_empty});
           this.password.textFocus();

         }else{
              this.setState({emptyInputFields:''});
              var params = {
                   "assword": this.state.password,
                   "UserName": this.state.username,
                   "LoginType": 'Manual',
              };

              this.webservicemanager.callWebService("LOGIN","TRANSACTION",params,(response) => {this.handleWebServiceCallResponse(response);});
         }
    }

    /* handle the web service successfull response error
    response will be handled inside WebServiceCallManager */

    handleWebServiceCallResponse(data){

        dismissKeyboard();

        var userData = {
            "username":this.state.username,
            "password":this.state.password
        }
        var passwordPolicy = {
          "passwordPolicy" : data.Body.Transaction.PasswordPolicy,
          "passwordPolicyRegex" : data.Body.Transaction.PasswordPolicyRegex
        }

        SessionManager.setSessionValue(Constants.FASTTRANSFER_BENEFICIARY_BRANCH_LIST,data.Body.Transaction.BranchList);
        SessionManager.setSessionValue(Constants.BENEFICIARY_COUNTRY,data.Body.Transaction.CountryList);
        SessionManager.setSessionValue(Constants.BENEFICIARY_RELATIONSHIP, data.Body.Transaction.RelationList);
        SessionManager.setSessionValue(Constants.LOGIN_USERDATA, userData);
        SessionManager.setSessionValue(Constants.CUSTOMER_NUMBER,data.Body.Transaction.CUSTNO);
        SessionManager.setSessionValue(Constants.PASSWORD_POLICY, passwordPolicy);
        SessionManager.setSessionValue(Constants.SECURITY_QUESTIONS_LIST,data.Body.Transaction.Questions);
        var nextScreenName = data.Body.Transaction.NextScreenName;

        const SpecificScreenClass = ScreenClass.getClassFromClassName(nextScreenName);
        SessionManager.setSessionValue('nextScreenName', nextScreenName);
        this.props.navigation.push(SpecificScreenClass);


        this.setState({
             username:'',
             password:'',
             emptyInputFields:''
        });
        this.userName.textClear();
        this.password.textClear();
        dismissKeyboard();

    }

    // handling text input field focus
   textHandler(){
     this.password.focus();
   }

   onSwitchToggle(value){
     if(value){
        opacity = 1;
      }
     else{
       opacity= 0.4;
     }
     this.setState({falseSwitchIsOn: value});
   }

     render(){
       this.fetchCredentials(this.webservicemanager,this.handleWebServiceCallResponse.bind(this));

          return(
               <View style={ styles.loginView}>
                 <Image style={ styles.loginViewBackground} source={loginBackgroundViewImg}>


                 <View>

                   <TextInputCustom
                        ref ={(ref) => this.userName = ref}
                        placeholder={langs.strings.login_userid_placeholder}
                        secureTextEntry={false}
                        onChangeTextCallback={val => this.setState({'username' : val})}
                        returnKeyType="next"
                        textInputWidth = {((width*86)/100)}
                        // onEndEditingCallback = {() => this.password.textFocus()}
                   />

                   <TextInputCustom
                        ref ={(ref) => this.password =ref}
                        placeholder={langs.strings.login_password_placeholder}
                        secureTextEntry={true}
                        onChangeTextCallback={val => this.setState({'password' : val})}
                        returnKeyType="done"
                        textInputWidth = {((width*86)/100)}
                   />
                   <Text style={ styles.emptyInputFields}>{this.state.emptyInputFields}</Text>
                 </View>
                 <View style={ styles.middleContainerViewButtons}>
                   <View style={ styles.middleContainerViewButtonsBtn}>
                     <TouchableHighlight onPress={ () => this.buttonsHandler('login')}>
                       <Text style={ styles.btnTextLabels}>{langs.strings.login_btnLogin}</Text>
                     </TouchableHighlight>
                   </View>
                   <View style={ styles.middleContainerViewButtonsBtn}>
                     <TouchableHighlight onPress={() => this.buttonsHandler('register')}>
                       <Text style={ styles.btnTextLabels}>{langs.strings.login_btnRegister}</Text>
                     </TouchableHighlight>
                   </View>
                 </View>
                 <TouchableHighlight onPress={() => {this.buttonsHandler('forgotpassword')}} underlayColor = {'transparent'}>
                   <Text style={ styles.labels} >
                     Forogot Password
                   </Text>
                 </TouchableHighlight>
                 <TouchableHighlight onPress={() => {this.buttonsHandler('forgotuserid')}} underlayColor = {'transparent'}>
                   <Text style={ styles.labels} >
                     Forogot User ID
                   </Text>
                 </TouchableHighlight>
                 <TouchableHighlight onPress={() => this.buttonsHandler('terms')} underlayColor = {'transparent'}>
                   <View >
                     <Text style={ styles.labels}>
                       {langs.strings.login_txtTermsAndConditions}
                     </Text>
                   </View>
                 </TouchableHighlight>
                 <View style={styles.fingerPrintLayout}>
                 <TouchableHighlight  underlayColor = {'transparent'}>
                   <View >
                     <Image style={styles.biometricImage} source={biometricImage}/>
                   </View>
                 </TouchableHighlight>
                   <View style={styles.switchRow} >
                   <Text style={ styles.labels} >
                     Enable Finger Print Login
                   </Text>
                     <Switch
                     onValueChange={(value) => this.onSwitchToggle(value) }
                     style={styles.switchControl}
                     value={this.state.falseSwitchIsOn} />
                   </View>
                   <Text>{this.state.message}</Text>
                 </View>

               </Image>
               <WebServiceCallManager visible={false} nav = {this.props.navigation} ref={ (input) => {this.webservicemanager = input;}}/>
             </View>
          );
     }

      fetchCredentials(web,resHandler) {
       if(this.state.phase === 'success') {
        Fingerprint.fetchCredentials(
          (...res) => {
              console.log(res);
              var params = {
                  "assword": res[1],
                  "UserName": res[0],
                  "LoginType": 'Biometric'
             };
             this.setState({username:params.UserName,password:params.Password,phase:''})
             this.webservicemanager.callWebService("LOGIN","TRANSACTION",params,(response) => {this.handleWebServiceCallResponse(response);},
             (err)=> {
             this.authenticate();});
            },
            (res) => {
                console.log(res);
                return null;
              }
        );
     }
   }

} // end of class

关于javascript - 在 React-Native 中处理服务调用的通用基类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42144822/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4