目标:
通过我的 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)
}
}
我目前的工作类,少数类是自定义类,如 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/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |