I am trying to get unread messages from PubNub. The process is like this:
I am not having the luck running these functions in order. That one is executed after the previous one is done.
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)
}
EDIT:
Looks like this is the problem with rendering too. When I get getUnreadedMessages()
then I am editing objects clients:
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);
});
based on this I am setting showIcon:
<ClientItem
client={item.item}
isAdmin={isAdmin}
navigation={navigation}
fromAdminTab={fromAdminTab}
showIcon={item.item.unreadMessages>0}
/>
But this icon is not showing corretly.
ClientList:
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;
ClientItem:
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;
I am not sure if it is because of fethichng data from Pubnub or because of rendering or how i process data in foreach.
Using async
and await
in an empirical coding style. This helps organize the code. Making the code easy to read. This helps also for order of operations.
What we did was add a return
in front of the await
and promise
in each function. That allows us to assign result variables after each function is finished executing while preserving order of execution as the code is written.
💡 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.
Test this by pressing the Run code snippet
button below the 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>