从 PubNub 获取未读消息并呈现通知
Fetch unread messages from PubNub and render notifications
我正在尝试从 PubNub 获取未读消息。过程是这样的:
- 设置赠款
- 获取频道元数据
- 获取未读消息等...
我运气不好 运行 这些函数按顺序排列。那个是在上一个完成后执行的。
async function setGrant(){
await pubnub.grant(
{
channels: [userId.toString() + '.*'],
ttl: 55,
read: true,
write: true,
update: true,
get: true,
},(status) => {
return new Promise(function (resolve) {
resolve(status)
});
});
}
async function getMetadata() {
await pubnub.objects.getAllChannelMetadata(
{
include: {
customFields: true
}
}).then((res: any) => {
return new Promise(function (resolve) {
resolve(setChannelMetadata(res.data));
});
});
}
async function getUnreadedMessages() {
await pubnub.messageCounts({
channels: channels,
channelTimetokens: tokens,
}).then((res: any) => {
console.log(res);
return new Promise(function (resolve) {
resolve(setUnreadMessage(res));
});
});
}
async function setChannelsAndTokens(){
channelMetadata.forEach((value, index) => {
tokens.push(value.custom.lastToken);
channels.push(value.id)
});
return new Promise(function (resolve) {
getUnreadedMessages()
resolve("Chanells and tokens set!");
})
}
function getUnreadMessagesProccess() {
return setGrant().then(getMetadata).then(setChannelsAndTokens).then(getUnreadedMessages)
}
编辑:
看起来这也是渲染的问题。当我得到 getUnreadedMessages()
然后我正在编辑对象客户:
clients.forEach((value, index) => {
if (res.channels[value.id + '-' + userId + '-chat']) {
value.unreadMessages = res["channels"][value.id + '-' + userId + '-chat'];
} else {
value.unreadMessages = 0;
}
console.log("UNREAD MESSAGE", value.unreadMessages, value.username);
});
基于此我设置 showIcon:
<ClientItem
client={item.item}
isAdmin={isAdmin}
navigation={navigation}
fromAdminTab={fromAdminTab}
showIcon={item.item.unreadMessages>0}
/>
但是这个图标没有正确显示。
客户名单:
import Colors from '@helper/Colors';
import { useSelector } from '@redux/index';
import { HealthierLifeOption } from '@redux/types';
import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
import ClientItem from './ClientItem';
import {usePubNub} from "pubnub-react";
export type Client = {
id: number;
username: string;
individualPlanPaid: boolean;
healthierLifeOption?: HealthierLifeOption;
company?: {
id: number;
companyName: string;
};
mentor?: {
id: number;
username: string;
};
}
type Props = {
navigation: any;
clients: Client[];
isAdmin?: boolean;
isLoading: boolean;
onEndReached: Function;
fromAdminTab?: boolean
}
const ClientList = ({ navigation, clients, onEndReached, isLoading, isAdmin = false, fromAdminTab= false }: Props) => {
const resultCount = useSelector(state => state.user.menteesResultCount);
const [hasMoreResults, setHasMoreResults] = useState(true);
const userId = useSelector(state => state.user.id);
const pubnub = usePubNub();
useEffect(() => {
getUnreadMessagesProccess
setHasMoreResults(resultCount !== clients?.length);
}, [resultCount, clients]);
async function setGrant() {
return new Promise( async resolve => {
await pubnub.grant({
channels: [
'100-68-chat',
'101-68-chat',
'22-2-chat',
'22-96-chat',
'73-68-chat',
'78-68-chat',
'79-68-chat',
'81-68-chat',
'90-68-chat',
'92-68-chat',
'93-68-chat',
'98-68-chat',
'99-68-chat' ],
ttl: 55,
read: true,
write: true,
update: true,
get: true,
}, response => resolve(response));
});
}
async function getMetadata() {
const options = {include: {customFields: true}};
return await pubnub.objects.getAllChannelMetadata(options);
}
function setChannelsAndTokens(channelMetadata, channels, tokens) {
channelMetadata.data.forEach((value, index) => {
tokens.push(value.custom.lastToken);
channels.push(value.id.toString())
});
}
async function getUnreadedMessages(channels, tokens) {
return new Promise(async resolve => {
pubnub.messageCounts({
channels: null,
channelTimetokens: tokens,
}).then(res => {
clients.forEach((value, index) => {
if (res.channels[value.id + '-' + userId + '-chat']) {
value.unreadMessages = res["channels"][value.id + '-' + userId + '-chat'];
} else {
value.unreadMessages = 0;
}
console.log("UNREAD MESSAGE", value.unreadMessages, value.username);
});
resolve()
})
.catch(error => resolve(error));
});
}
async function getUnreadMessagesProccess() {
const tokens = ['1000'];
const channels = ['1234567'];
const userId = 1234567;
const auth = await setGrant(userId);
log([{statusCode: auth.statusCode}]);
const channelMetadata = await getMetadata();
log([channelMetadata,channels,tokens]);
setChannelsAndTokens(channelMetadata, channels, tokens);
const unread = await getUnreadedMessages(channels, tokens);
log([unread]);
return unread;
}
return (
<View>
<FlatList
keyExtractor={item => item.id.toString()}
data={clients}
onEndReached={() => hasMoreResults ? onEndReached() : null}
onEndReachedThreshold={0.4}
renderItem={item => (
<ClientItem
client={item.item}
isAdmin={isAdmin}
navigation={navigation}
fromAdminTab={fromAdminTab}
showIcon={parseInt(item.item.unreadMessages) > 0 }
/>
)}
ListFooterComponent={isLoading
? () => (
<View style={{ padding: 20 }}>
<ActivityIndicator animating size="large" color={Colors.border_gray} />
</View>
)
: null
}
/>
</View>
);
}
export default ClientList;
客户项目:
import React, {useEffect, useState} from 'react';
import { Text, View, Image, TouchableOpacity } from 'react-native';
import Images from '@helper/Images';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import Colors from '@helper/Colors';
import styles from '../styles';
import ClientModal from './ClientModal/ClientModal';
import { Client } from './ClientList';
import { HealthierLifeOption } from '@redux/types';
type Props = {
client: Client;
navigation: any;
isAdmin?: boolean;
fromAdminTab?: boolean;
showIcon?: boolean
}
const ClientItem = ({ client, navigation, isAdmin = false, fromAdminTab= false, showIcon= false }: Props) => {
const [showModal, setShowModal] = useState(false);
console.log(showIcon); // its not passed correclty
let clientIcon = Images.icon.logoIconOrange
const handleContinueButton = () => {
if(!fromAdminTab) {
navigation.navigate('ChatFromClientsList', { selectedId: client.id, showBackButton: true });
}else {
setShowModal(!showModal)
}
};
return (
<View style={styles.client_item_container}>
<TouchableOpacity style={styles.client_content_container} onPress={handleContinueButton}
>
<View style={styles.image_container}>
<Image
style={styles.client_profile_img}
source={clientIcon}
resizeMode="contain"
resizeMethod="resize"
/>
</View>
<View style={styles.title_container}>
<Text style={styles.title} >{ client.username } </Text>
</View>
<View style={styles.dot_container}>
{showIcon && <FontAwesome5
name="comment-dots"
size={20}
color={Colors.red}
/> }
</View>
<View style={styles.hamburger_container} >
<FontAwesome5
name="bars"
size={30}
color={Colors.black}
onPress={() => setShowModal(!showModal)}
/>
</View>
<View>
<ClientModal
isVisible={showModal}
onCollapse={(value: boolean) => setShowModal(value)}
closeModal={(value: boolean) => setShowModal(value)}
client={client}
navigation={navigation}
isAdmin={isAdmin}
/>
</View>
</TouchableOpacity>
</View>
);
};
export default ClientItem;
我不确定这是因为来自 Pubnub 的 fethichng 数据还是因为渲染或我如何处理 foreach 中的数据。
运行 上一个完成后的函数
在经验编码风格中使用 async
和 await
。这有助于组织代码。使代码易于阅读。这也有助于操作顺序。
我们所做的是在每个函数的await
和promise
前面添加一个return
。这允许我们在每个函数完成执行后分配结果变量,同时在编写代码时保留执行顺序。
Note: when the SDK is initialized with the secretKey
, there is no need to grant yourself access to resources. Simply use any method as if you already had permissions. The SDK will automatically sign all requests using the your secret key.
按代码段下方的 Run code snippet
按钮进行测试。
(async ()=>{
'use strict';
const publishKey = "pub-c-51f1008b-7ddf-42b7-aec9-2d0153b0e766";
const subscribeKey = "sub-c-1597b696-05af-11e6-a6dc-02ee2ddab7fe";
const secretKey = "sec-c-YTVjYjUzMWMtM2MxZC00YzdiLWE0ZjAtNWRmMWVmYmNkZGNl";
const myUUID = "myUniqueUUID"
const pubnub = new PubNub({
publishKey : publishKey,
subscribeKey : subscribeKey,
secretKey : secretKey,
uuid : myUUID,
});
const unread = await getUnreadMessagesProccess();
async function getUnreadMessagesProccess() {
const tokens = ['1000']; // placeholder change me
const channels = ['1234567']; // placeholder change me
const userId = 1234567; // placeholder change me
const auth = await setGrant(userId);
log([{statusCode: auth.statusCode}]);
const channelMetadata = await getMetadata();
log([channelMetadata,channels,tokens]);
setChannelsAndTokens(channelMetadata, channels, tokens);
const unread = await getUnreadedMessages(channels, tokens);
log([unread]);
return unread;
}
async function setGrant(userId) {
return new Promise( async resolve => {
await pubnub.grant({
channels: [userId.toString() + '.*'],
ttl: 55,
read: true,
write: true,
update: true,
get: true,
}, response => resolve(response));
});
}
async function getMetadata() {
const options = {include: {customFields: true}};
return await pubnub.objects.getAllChannelMetadata(options);
}
function setChannelsAndTokens(channelMetadata, channels, tokens) {
channelMetadata.data.forEach((value, index) => {
tokens.push(value.custom.lastToken);
channels.push(value.id)
});
}
async function getUnreadedMessages(channels, tokens) {
try {
return await pubnub.messageCounts({
channels: channels,
channelTimetokens: tokens,
});
}
catch(error) {
return error;
}
}
async function getUnreadedMessagesAlternative(channels, tokens) {
return new Promise(async resolve => {
pubnub.messageCounts({
channels: channels,
channelTimetokens: tokens,
}).then(result => resolve(result))
.catch(error => resolve(error));
});
}
function log(data) {
// console.log(data);
document.querySelector("#out").innerHTML +=
`<div>${JSON.stringify(data)}</div>`;
}
})();
<div id="out"></div>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.33.0.js"></script>
我正在尝试从 PubNub 获取未读消息。过程是这样的:
- 设置赠款
- 获取频道元数据
- 获取未读消息等...
我运气不好 运行 这些函数按顺序排列。那个是在上一个完成后执行的。
async function setGrant(){
await pubnub.grant(
{
channels: [userId.toString() + '.*'],
ttl: 55,
read: true,
write: true,
update: true,
get: true,
},(status) => {
return new Promise(function (resolve) {
resolve(status)
});
});
}
async function getMetadata() {
await pubnub.objects.getAllChannelMetadata(
{
include: {
customFields: true
}
}).then((res: any) => {
return new Promise(function (resolve) {
resolve(setChannelMetadata(res.data));
});
});
}
async function getUnreadedMessages() {
await pubnub.messageCounts({
channels: channels,
channelTimetokens: tokens,
}).then((res: any) => {
console.log(res);
return new Promise(function (resolve) {
resolve(setUnreadMessage(res));
});
});
}
async function setChannelsAndTokens(){
channelMetadata.forEach((value, index) => {
tokens.push(value.custom.lastToken);
channels.push(value.id)
});
return new Promise(function (resolve) {
getUnreadedMessages()
resolve("Chanells and tokens set!");
})
}
function getUnreadMessagesProccess() {
return setGrant().then(getMetadata).then(setChannelsAndTokens).then(getUnreadedMessages)
}
编辑:
看起来这也是渲染的问题。当我得到 getUnreadedMessages()
然后我正在编辑对象客户:
clients.forEach((value, index) => {
if (res.channels[value.id + '-' + userId + '-chat']) {
value.unreadMessages = res["channels"][value.id + '-' + userId + '-chat'];
} else {
value.unreadMessages = 0;
}
console.log("UNREAD MESSAGE", value.unreadMessages, value.username);
});
基于此我设置 showIcon:
<ClientItem
client={item.item}
isAdmin={isAdmin}
navigation={navigation}
fromAdminTab={fromAdminTab}
showIcon={item.item.unreadMessages>0}
/>
但是这个图标没有正确显示。
客户名单:
import Colors from '@helper/Colors';
import { useSelector } from '@redux/index';
import { HealthierLifeOption } from '@redux/types';
import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
import ClientItem from './ClientItem';
import {usePubNub} from "pubnub-react";
export type Client = {
id: number;
username: string;
individualPlanPaid: boolean;
healthierLifeOption?: HealthierLifeOption;
company?: {
id: number;
companyName: string;
};
mentor?: {
id: number;
username: string;
};
}
type Props = {
navigation: any;
clients: Client[];
isAdmin?: boolean;
isLoading: boolean;
onEndReached: Function;
fromAdminTab?: boolean
}
const ClientList = ({ navigation, clients, onEndReached, isLoading, isAdmin = false, fromAdminTab= false }: Props) => {
const resultCount = useSelector(state => state.user.menteesResultCount);
const [hasMoreResults, setHasMoreResults] = useState(true);
const userId = useSelector(state => state.user.id);
const pubnub = usePubNub();
useEffect(() => {
getUnreadMessagesProccess
setHasMoreResults(resultCount !== clients?.length);
}, [resultCount, clients]);
async function setGrant() {
return new Promise( async resolve => {
await pubnub.grant({
channels: [
'100-68-chat',
'101-68-chat',
'22-2-chat',
'22-96-chat',
'73-68-chat',
'78-68-chat',
'79-68-chat',
'81-68-chat',
'90-68-chat',
'92-68-chat',
'93-68-chat',
'98-68-chat',
'99-68-chat' ],
ttl: 55,
read: true,
write: true,
update: true,
get: true,
}, response => resolve(response));
});
}
async function getMetadata() {
const options = {include: {customFields: true}};
return await pubnub.objects.getAllChannelMetadata(options);
}
function setChannelsAndTokens(channelMetadata, channels, tokens) {
channelMetadata.data.forEach((value, index) => {
tokens.push(value.custom.lastToken);
channels.push(value.id.toString())
});
}
async function getUnreadedMessages(channels, tokens) {
return new Promise(async resolve => {
pubnub.messageCounts({
channels: null,
channelTimetokens: tokens,
}).then(res => {
clients.forEach((value, index) => {
if (res.channels[value.id + '-' + userId + '-chat']) {
value.unreadMessages = res["channels"][value.id + '-' + userId + '-chat'];
} else {
value.unreadMessages = 0;
}
console.log("UNREAD MESSAGE", value.unreadMessages, value.username);
});
resolve()
})
.catch(error => resolve(error));
});
}
async function getUnreadMessagesProccess() {
const tokens = ['1000'];
const channels = ['1234567'];
const userId = 1234567;
const auth = await setGrant(userId);
log([{statusCode: auth.statusCode}]);
const channelMetadata = await getMetadata();
log([channelMetadata,channels,tokens]);
setChannelsAndTokens(channelMetadata, channels, tokens);
const unread = await getUnreadedMessages(channels, tokens);
log([unread]);
return unread;
}
return (
<View>
<FlatList
keyExtractor={item => item.id.toString()}
data={clients}
onEndReached={() => hasMoreResults ? onEndReached() : null}
onEndReachedThreshold={0.4}
renderItem={item => (
<ClientItem
client={item.item}
isAdmin={isAdmin}
navigation={navigation}
fromAdminTab={fromAdminTab}
showIcon={parseInt(item.item.unreadMessages) > 0 }
/>
)}
ListFooterComponent={isLoading
? () => (
<View style={{ padding: 20 }}>
<ActivityIndicator animating size="large" color={Colors.border_gray} />
</View>
)
: null
}
/>
</View>
);
}
export default ClientList;
客户项目:
import React, {useEffect, useState} from 'react';
import { Text, View, Image, TouchableOpacity } from 'react-native';
import Images from '@helper/Images';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import Colors from '@helper/Colors';
import styles from '../styles';
import ClientModal from './ClientModal/ClientModal';
import { Client } from './ClientList';
import { HealthierLifeOption } from '@redux/types';
type Props = {
client: Client;
navigation: any;
isAdmin?: boolean;
fromAdminTab?: boolean;
showIcon?: boolean
}
const ClientItem = ({ client, navigation, isAdmin = false, fromAdminTab= false, showIcon= false }: Props) => {
const [showModal, setShowModal] = useState(false);
console.log(showIcon); // its not passed correclty
let clientIcon = Images.icon.logoIconOrange
const handleContinueButton = () => {
if(!fromAdminTab) {
navigation.navigate('ChatFromClientsList', { selectedId: client.id, showBackButton: true });
}else {
setShowModal(!showModal)
}
};
return (
<View style={styles.client_item_container}>
<TouchableOpacity style={styles.client_content_container} onPress={handleContinueButton}
>
<View style={styles.image_container}>
<Image
style={styles.client_profile_img}
source={clientIcon}
resizeMode="contain"
resizeMethod="resize"
/>
</View>
<View style={styles.title_container}>
<Text style={styles.title} >{ client.username } </Text>
</View>
<View style={styles.dot_container}>
{showIcon && <FontAwesome5
name="comment-dots"
size={20}
color={Colors.red}
/> }
</View>
<View style={styles.hamburger_container} >
<FontAwesome5
name="bars"
size={30}
color={Colors.black}
onPress={() => setShowModal(!showModal)}
/>
</View>
<View>
<ClientModal
isVisible={showModal}
onCollapse={(value: boolean) => setShowModal(value)}
closeModal={(value: boolean) => setShowModal(value)}
client={client}
navigation={navigation}
isAdmin={isAdmin}
/>
</View>
</TouchableOpacity>
</View>
);
};
export default ClientItem;
我不确定这是因为来自 Pubnub 的 fethichng 数据还是因为渲染或我如何处理 foreach 中的数据。
运行 上一个完成后的函数
在经验编码风格中使用 async
和 await
。这有助于组织代码。使代码易于阅读。这也有助于操作顺序。
我们所做的是在每个函数的await
和promise
前面添加一个return
。这允许我们在每个函数完成执行后分配结果变量,同时在编写代码时保留执行顺序。
Note: when the SDK is initialized with the
secretKey
, there is no need to grant yourself access to resources. Simply use any method as if you already had permissions. The SDK will automatically sign all requests using the your secret key.
按代码段下方的 Run code snippet
按钮进行测试。
(async ()=>{
'use strict';
const publishKey = "pub-c-51f1008b-7ddf-42b7-aec9-2d0153b0e766";
const subscribeKey = "sub-c-1597b696-05af-11e6-a6dc-02ee2ddab7fe";
const secretKey = "sec-c-YTVjYjUzMWMtM2MxZC00YzdiLWE0ZjAtNWRmMWVmYmNkZGNl";
const myUUID = "myUniqueUUID"
const pubnub = new PubNub({
publishKey : publishKey,
subscribeKey : subscribeKey,
secretKey : secretKey,
uuid : myUUID,
});
const unread = await getUnreadMessagesProccess();
async function getUnreadMessagesProccess() {
const tokens = ['1000']; // placeholder change me
const channels = ['1234567']; // placeholder change me
const userId = 1234567; // placeholder change me
const auth = await setGrant(userId);
log([{statusCode: auth.statusCode}]);
const channelMetadata = await getMetadata();
log([channelMetadata,channels,tokens]);
setChannelsAndTokens(channelMetadata, channels, tokens);
const unread = await getUnreadedMessages(channels, tokens);
log([unread]);
return unread;
}
async function setGrant(userId) {
return new Promise( async resolve => {
await pubnub.grant({
channels: [userId.toString() + '.*'],
ttl: 55,
read: true,
write: true,
update: true,
get: true,
}, response => resolve(response));
});
}
async function getMetadata() {
const options = {include: {customFields: true}};
return await pubnub.objects.getAllChannelMetadata(options);
}
function setChannelsAndTokens(channelMetadata, channels, tokens) {
channelMetadata.data.forEach((value, index) => {
tokens.push(value.custom.lastToken);
channels.push(value.id)
});
}
async function getUnreadedMessages(channels, tokens) {
try {
return await pubnub.messageCounts({
channels: channels,
channelTimetokens: tokens,
});
}
catch(error) {
return error;
}
}
async function getUnreadedMessagesAlternative(channels, tokens) {
return new Promise(async resolve => {
pubnub.messageCounts({
channels: channels,
channelTimetokens: tokens,
}).then(result => resolve(result))
.catch(error => resolve(error));
});
}
function log(data) {
// console.log(data);
document.querySelector("#out").innerHTML +=
`<div>${JSON.stringify(data)}</div>`;
}
})();
<div id="out"></div>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.33.0.js"></script>