它山之石可以攻玉
import { Alert, AsyncStorage }from 'react-native';
import userStore from '../store/user/userStore';
import joinInOfferStore from '../store/home/joinInOfferStore';
import { Actions }from 'react-native-router-flux';
var moment =require('moment');
init({
size:10000,
// storageBackend: AsyncStorage,
defaultExpires:1000 *3600 *24,
enableCache:true,
// reconnect: true,
reconnect:false,
sync: {},
});
// var client = new Paho.MQTT.Client('121.41.177.80', 15675, '/ws', 'clintId');
var client =new Paho.MQTT.Client('121.41.177.80', 15675, '/ws', String(new Date().getTime())); //以时间戳作为clientId,注意clientId固定时会出现多台设备只接受一个消息的情况,'121.41.177.80', 15675, 这两个参数一个uri,一个端口,都是看后端怎么配。
//onConnectionLost是mqtt断连的情况下自动掉用的方法,可以用来查看mqtt连接失败的原因,我这里用来在断连时重新调起连接服务
function onConnectionLost(responseObject) {
if (responseObject.errorCode !==0) {
console.log('onConnectionLost:' + responseObject.errorMessage);
console.log('=====重新连接0', userStore.loginUser);
if (userStore.loginUser) {
client.connect({
useSSL:false,
password:'aaaaaa', //问后端
userName:'admin', //问后端
cleanSession:false,
timeout:6000,
onSuccess: () => {
// 主题
let topic =userStore.loginUser.id +'@' +userStore.loginUser.userPhone; //这边的主题是用账号的id和手机号,目的是后台能根据人来进行消息分发,如果固定是发给所有人的话可以直接定死‘dev’之类的。
client.subscribe(topic);
console.log('=====重新订阅成功');
},
onFailure: (e) => {
console.log('失败');
console.log(e);
},
});
}
}
}
function onMessageArrived(message) {
console.log('onMessageArrived:' + message.payloadString);
}
client.onConnectionLost =onConnectionLost;
client.onMessageArrived =onMessageArrived;
client.connect({
useSSL:false,
password:'aaaaaa',
userName:'admin',
timeout:6000,
// keepAliveInterval: 60,
cleanSession:false,
onSuccess: () => {
console.log('===成功连接');
},
onFailure: (e) => {
console.log('失败');
console.log(e);
},
});
\
export const messageMq = (callback) => {
let topic = callback.id +'@' + callback.userPhone;
console.log('======topic', topic, typeof topic);
// this.timer1 = setTimeout(() => {
client.subscribe(topic);
// }, 200);
// // // 接受消息
client.onMessageArrived =function (message) {
let temp =JSON.parse(message.payloadString);
joinInOfferStore.orderId =Number(temp.msgContent);
Alert.alert('提示', '有招标订单内容变更', [
{text:'忽略' },
{
text:'立即查看',
onPress:doLogOut,
},
]);
};
};
const doLogOut = () => {
Actions.push('JoinInOffer');
};
1.新建文件夹在src目录下的native文件夹(随意,这里是我的位置,在这个目录下MessageMq.js文件会在项目启动时调用,也就是发起client.connect方法,连接服务端,但不订阅,因为我的topic此时还没有拿到,所以只连接,不订阅)
2.export一个messageMq方法,这是用来在获取到topic(我这边是账号id和手机号)时在其他页面调用来订阅(client.subscribe(topic))并接收消息的。
let topic = callback.id +'@' + callback.userPhone;
console.log('======topic', topic, typeof topic);
// this.timer1 = setTimeout(() => {
client.subscribe(topic);
// }, 200);
// // // 接受消息
client.onMessageArrived =function (message) {
let temp =JSON.parse(message.payloadString);
joinInOfferStore.orderId =Number(temp.msgContent);
Alert.alert('提示', '有招标订单内容变更', [
{text:'忽略' },
{
text:'立即查看',
onPress:doLogOut,
},
]);
};
};
3.在可以稳定获取账号id和手机号的页面(app的项目首页)调用messageMq方法,订阅并接收消息。
onRefresh = (isRefresh =true) => {
const { orderStore, userStore } =this.props;
orderStore
.getMyDoingOrder(isRefresh)
.then(() => {
orderStore.getMyOrderNum().catch((error) => {
MessageService.showError('获取数据失败', `${error.message}`);
});
{
(userStore.loginUser && userStore.loginUser.authType ==='car_captain') ||
(userStore.loginUser && userStore.loginUser.authType ==='car_captain_temp')
?null
:messageMq(this.props.userStore.loginUser); ////调用messageMq方法
}
})
.catch((error) => {
if (error =='Error: AMQJS0011E Invalid state not connected.') {
MessageService.showError('网络不稳定', '您可能无法接收到招标订单修改提醒');
}else {
// MessageService.showError('获取订单列表失败', `${error.message}`)
}
});
};
\
一开始我是在componentDidMount下调用的messageMq但经常因为断连或者其他问题(网络问题,或者服务端链接不稳定,毕竟是免费的)报红导致app闪退,所以这边在函数里面调用,当client.subscribe(topic)抛出异常了,函数能够捕捉到,然后给出提示是因为网络回或者服务端问题没有连接上。
注:第一次弄mqtt,短短续续搞了2个礼拜,最后勉强达到预期的功能吧,但是我知道这边写法肯定是有点问题的,但是确实也是想不到什么好办法了,希望能对你有用,如果有疑问,可以评论,会回复的,写了几篇文章,竟然还没有评论的,是我写的太水了吗······如果有路过的大神有更好的写法,希望能私信或者评论分享,实在是相关文章太少且我本人水平有限。