我正在使用React-Native创建一个应用程序,并使用websocket接收数据。 但是,当我按下主页按钮使我的应用程序在后台运行时,websocket将被暂停,当我再次单击我的应用程序时,websocket将继续运行,这是完全可以的,但是我的问题是我的应用程序在后台模式下运行超过10次分钟,当我再次打开我的应用程序时,websocket完全停止了。我该如何解决这个问题?
我知道我可以使用Appstate来检测我的应用程序是否处于后台模式。但是我认为那不是我现在真正需要的!
还有另一个类似的问题:
如果用户留在应用程序中但手机自动锁定并且再次打开手机时,websocket也已关闭怎么办。 如何让websocket再次继续?
有什么想法吗?
答案 0 :(得分:3)
我们有一个使用websockets的应用程序,我们的问题是在重新启动REST服务器的情况下,所有客户端都应重新打开Web套接字。因此,我们使用setInterval以固定速率ping服务器,并在出现错误时重新创建套接字,这是我们的套接字管理器类的代码:
export default class SocketManager {
constructor(endPoint, handlers) {
this.endPoint = endPoint;
this.handlers = handlers;
this.createSocket();
}
createSocket() {
if (this.interval) clearInterval(this.interval);
this.socket = this.buildSocket();
this.pings = 0;
this.pongs = 0;
this.interval = setInterval(() => {
this.socket.send("ping");
this.pings++;
}, 3000);
}
closeSocket = () => {
console.log("Cerrando socket");
if (this.interval) clearInterval(this.interval);
this.socket.close();
};
reconnect = () => {
this.createSocket();
};
buildSocket = () => {
const sock = new WebSocket(this.endPoint);
sock.onerror = error => {
console.log("error", error);
setTimeout(() => this.reconnect(), 3000);
};
sock.onmessage = ({ data }) => {
if (data === "pong") {
this.pongs++;
console.log(`${this.pings} pings, ${this.pongs} pongs`);
return;
}
const handler = this.handlers[data];
if (handler) {
handler();
}
};
return sock;
};
}
我们是通过redux动作创建者来调用它的,例如:
const doLogin = ({ email, password }) => {
const body = doFormBody({ email, password });
// // //console.log(`endPoint es ${ENDPOINT}`);
return dispatch => {
dispatch({ type: CONECTANDO });
const url = `${ENDPOINT}/rest/login`;
fetch(url, {
headers: {
Accept: "application/json",
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
method: "POST",
body
})
.then(response => response.json())
.then(json => {
if (json.error) dispatch({ type: LOGIN_ERROR, payload: json.error });
else {
dispatch({ type: LOGGED_IN, payload: json });
const adultosSocket = crearSocket(dispatch, json.id);
dispatch({ type: ESTABLECE_SOCKET, payload: adultosSocket });
}
})
.catch(err => {
dispatch({ type: LOGIN_ERROR, payload: err.message });
});
};
};
该操作使用此帮助器函数最终创建套接字。随时保持仅一个套接字实例发送ping十分重要。
const crearSocket = (dispatch, userId) => {
const endPoint = `${WS_ENDPOINT}/usuarioConectado?userId=${userId}`;
const handlers = {
reload: () => {
const url = `${ENDPOINT}/rest/adultos/${userId}`;
fetch(url)
.then(response => response.json())
.then(json => dispatch({ type: ADULTOS_CARGADOS, payload: json }))
.catch(err => dispatch({ type: ADULTOS_ERROR, payload: err.message }));
}
};
return new SocketManager(endPoint, handlers);
};
这不是玩具代码,实际上在我们的应用程序中运行,因此可以正常工作。