I am trying to do an infinite scrolling, it works fine by just increasing the first value. However, I would like to fetch for new edges prepending to the beginning. How can I do that without force fetching?
This is my RelayContainer, where firstLoad and afterFirst referring to the same connection with different arguments, using alias. Relay doesn't query for the anything before. I have also forcefully set hasNextPage and hasPreviousPage to true from graphql server side
How does relay decides whether to fetch new edge from server
constructor(props) {
super(props);
if (!props.viewer) {
this.handleLogout();
console.log('Access expired.');
return;
}
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => {
return r1.cursor !== r2.cursor;
}});
this.state = {
dataSource: ds.cloneWithRows(props.viewer.firstLoad.edges),
};
}
componentWillMount() {
// Set up to query for newly received messages
const {edges} = this.props.viewer.firstLoad;
this.props.relay.setVariables({
last: edges.length,
before: edges[edges.length - 1].cursor,
});
}
componentDidMount() {
this._interval = setInterval(() => {
this.props.relay.setVariables({
last: this.props.relay.variables.last + 10,
});
}, 2000);
}
componentWillReceiveProps(nextProps) {
const {edges} = nextProps.viewer.afterFirst;
if (edges) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(edges),
});
}
}
I have successfully solved my requirement by creating a new field that returns new items after a cursor/timestamp, and manually maintaining an array of data that's used for displaying, populated by data from Relay.
One key takeaway is to concat the variables with some random data so that setVariables will make a request to the server instead of the cache.
startPolling() {
this._timer = setTimeout(() => {
this.props.relay.setVariables({
lastCreatedAt: `${this._lastCreatedAt}:${new Date().getTime()}`,
});
this.startPolling();
}, 5000);
}
Related
var express = require("express")
let PersonModel = require('./PersonModel')
let mongodbConnected=require('./MongodbConnect')
var app =express()
var bodyparser=require("body-parser")
const { format } = require("path")
const { count } = require("console")
const { countDocuments } = require("./PersonModel")
const { exec } = require("child_process")
const { get } = require("http")
const { ALL } = require("dns")
app.use(bodyparser.urlencoded({extended:false}))
app.get('/',function(req,res){
res.sendFile('Person.html', { root: __dirname });
})
app.get('/about',function (req,res){
res.send("This is a simple express application using mongodb express html and mongoose")
PersonModel.countDocuments().exec()
.then(count=>{
console.log("Total documents Count before addition :", count)
}) .catch(err => {
console.error(err)
})
})
app.post('/add', function(req,res){
Pname=req.body.empname
console.log('Pname',Pname)
PAge=req.body.Age
PGender=req.body.gender
PSalary=req.body.salary
const doc1 = new PersonModel(
{
name:Pname,age:33,Gender:PGender,Salary
:PSalary}
)
doc1.save(function(err,doc){
if (err) return console.error(err)
else
console.log("doc is added ",doc)
//res.send("Record is added"+doc)
res.send({
'status':true,
'Status_Code':200,
'requested at': req.localtime,
'requrl':req.url,
'request Method':req.method,
'RecordAdded':doc});
}
)
})
app.post('/findperson', function(req,res){
PAge=req.body.Age
console.log("Page",PAge)
PersonModel.find({age:{$gte:PAge}})
// find all users
.sort({Salary: 1}) // sort ascending by firstName
.select('name Salary age')// Name and salary only
.limit(10) // limit to 10 items
.exec() // execute the query
.then(docs => {
console.log("Retrieving records ",docs)
res.send(docs)
})
.catch(err => {
console.error(err)})
})
app.post('/delete', function(req,res){
Pgender=req.body.gender
PersonModel.findOneAndDelete({Gender:Pgender }
).exec()
.then(docs=>{
console.log("Deleted")
console.log(docs); // Success
}).catch(function(error){
console.log(error); // Failure
});
})
app.post('/update', function(req,res){
Pname=req.body.empname
Pnewname=req.body.newname
PnewAge=req.body.newage
PersonModel.findOneAndUpdate({ name: Pname },{"$set":{name:Pnewname,age:PnewAge}}).exec()
.then(docs=>{
console.log("Update for what i get is ",Pname
,Pnewname,PnewAge)
console.log(docs); // Success
}).catch(function(error){
console.log(error); // Failure
});
})
var docnum=PersonModel.countDocuments(ALL)
app.post('/count', function(req, res){
res.send('Total number of documents: ', docnum)
})
app.listen(5000,function(){
console.log("Server is running on the port 5000")
})
Hello.
First time posting on stackoverflow, dont know what kind of information to post, please let me know.
Im trying to make a page (/count) to simply display the number of documents. I've tried different code but nothing is working. This error keeps coming up "TypeError: Converting circular structure to JSON".
This is school work so the code is given to me by a teacher and I have to add a POST method to add a page that displays total number of documents.
Any ideas?
Thanks.
Circular structure is not about mongo but how JS read the JSON object.
For example, if you have this object:
var object = {
propA: "propA",
propB: object
}
When JS try to deserialize JSON object, will handle that: One object contains the object that contain again the object and again and again... that is a circular dependence.
Not only with one object itself, aslo with more objects:
var objectA = {
propA: objectB
}
var objectB = {
propA: objectA
}
Is the same case.
Using node.js you can use util.inspecet() which automatically show [Circular] when a circular dependence is found.
You can use like this:
var util = require('util')
console.log(util.inspect(objectA))
I am currently working on a project which requires me to make multiple queries/mutations. I tried setting up my apollo client with BatchHttpLink and I can see the data I am requesting in the network tab in the browser. It is coming back at an array of objects instead of JSON.
But the issue is when I try to grab the data in my component data is undefined. I tried using HttpLink instead of BatchHttpLink and I can get the data back from the hook.
My suspicion is the shape of the object that comes back from the response is different, I tried looking into documentation but I can't find much about batching.
Currently using "#apollo/client#^3.0.2"
Here's my client set up.
import { ApolloClient, InMemoryCache, ApolloLink, from } from '#apollo/client'
import { BatchHttpLink } from '#apollo/client/link/batch-http'
import { onError } from '#apollo/client/link/error'
const BASE_URL = 'http://localhost:4000'
const httpLink = new BatchHttpLink({
uri: BASE_URL,
credentials: 'include',
})
const csrfMiddleware = new ApolloLink((operation, forward) => {
operation.setContext(({ headers = {} }) => ({
headers: {
...headers,
'X-CSRF-Token': getCSRFToken(),
},
}))
return forward(operation)
})
const errorMiddleware = onError(({ networkError }) => {
if (networkError && 'statusCode' in networkError && networkError.statusCode === 401) {
window.location.assign('/accounts/login')
}
})
const client = new ApolloClient({
link: from([errorMiddleware, csrfMiddleware, httpLink]),
cache: new InMemoryCache(),
})
This is the react hook I'm trying to console log.
const {data} = useQuery(GET_USER_PERMISSIONS_AND_PREFERENCES)
Figured it out. You need to add another middleware to return the data that the useQuery hook can recognize. The data that comes back in the batch call is an array of objects shaped
{
payload: {
data: { ... }
}
}
So something like this did the trick for me
const batchParseMiddleware = new ApolloLink((operation, forward) => {
return forward(operation).map((data: any) => data.payload)
})
I have been having a similar issue, and have so far only been able to solve it by breaking batching and converting to a normal HttpLink
So backstop.js provides ability to run custom script against underlying engine. I use puppeteer as an engine so I try to mock Date.now with 'onReadyScript':
page.evaluate('window.Date.now = () => 0; Date.now = () => 0;');
...
page.addScriptTag({
// btw `console.log` here is not executed, do I use it in wrong way?
content: 'Date.now = () => 0;'
});
...
page.evaluate(() => {
window.Date.now = () => 0;
Date.now = () => 0;
});
Last one, I think, is modifying Date in context of Node, not inside the puppeteer, but anyway tried that as well.
Nothing worked, script under the test still output real Date.now. Also I checked Override the browser date with puppeteer but it did not help me.
Yes, I know I'm able to skip particular selectors, but it does not always make sense(think about clock with arrows).
After trying onBeforeScript with evaluateOnNewDocument() it works for me. Complete script:
module.exports = async function (page, scenario) {
if (!page.dateIsMocked) {
page.dateIsMocked = true
await page.evaluateOnNewDocument(() => {
const referenceTime = '2010-05-05 10:10:10.000';
const oldDate = Date;
Date = function(...args) {
if (args.length) {
return new oldDate(...args);
} else {
return new oldDate(referenceTime);
}
}
Date.now = function() {
return new oldDate(referenceTime).valueOf();
}
Date.prototype = oldDate.prototype;
})
}
};
Reason: onReadyScript is executed when page under testing has already been loaded and executed. So code is bound to original Date by closure, not the mocked version.
I am saving some settings using the following sequence
var getSettings = async function() {
var settings;
try {
settings = await authenticatedGET(server_url + SETTINGS_ENDPOINT);
return settings;
} catch (error) {
console.log("Settings Fetch Failed: " + error);
throw new Error(error);
}
}
const setLocalSettings = function(settings) {
chrome.storage.sync.set({ 'LML_Settings': JSON.parse(settings) }, function() {
console.log("Settings saved locally");
});
}
At the line right after the setLocalSettings function definition, the 'settings' object logs out as
{"email_format":"individual","close_tab":true,"frequency":"DAILY"} (correctly as intended). When I go to fetch the settings using this sequence:
chrome.storage.sync.get('LML_Settings', function(LMLSettingsContainer) {
console.log(LMLSettingsContainer);
if (LMLSettingsContainer.LML_settings.close_tab == "true") {
closeCurrentTab();
}
})
LMLSettingsContainer logs out as
{
"LML_Settings": {
"close_tab": true,
"email_format": "individual",
"frequency": "DAILY"
}
}
accessing my settings with LMLSettingsContainer.LML_Settings["<setting>"] is a bit annoying (and its the whole reason I named the top variable LMLSettingsContainer).
Does anyone know if there's a way to have chrome save/get these values unwrapped?
chrome.storage.sync.get('LML_Settings', ({LML_settings}) => { ... }) works, per #wOxxOm
I have been trying to get WebRTC to function with a broadcaster and multiple listeners but am stuck when it comes to transferal descriptions and candidates via signalling (with nodejs & socket.io).
I can get the process working between two browsers with a simple nodejs socket app which simply broadcasts the descriptions and candidates to other already connected clients, but when I attempt to store a description and connect with a newly opened browser, nothing happens.
What I basically need to understand is what do I need to provide to one browser, in order for it to begin communicating with another? The project I am working on requires the ability for listeners to join rooms, authenticate, and begin listening to whatever media is being sent.
Below is my client side code:
var audioContext = new webkitAudioContext()
var client = null
var configuration =
{
'iceServers':
[{
'url': 'stun:stun.example.org'
}]
}
$(function ()
{
window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection
client = new RTCPeerConnection(configuration, { optional:[ { RtpDataChannels: true } ]})
client.onnegotiationneeded = function ()
{
console.log('Negotiation needed')
createOffer()
}
client.onicecandidate = function (event)
{
console.log('onicecandidate')
socket.emit('candidate', JSON.stringify({ 'candidate': event.candidate }))
}
client.onaddstream = function (event)
{
console.log('onaddstream')
$('#player').attr('src', URL.createObjectURL(event.stream))
player.play()
}
socket.on('candidate', function (event)
{
candidate(event)
})
socket.on('description', function (message)
{
if(!client) { return }
client.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
if (client.remoteDescription.type == 'offer')
client.createAnswer(function (description)
{
client.setLocalDescription(description, function ()
{
socket.emit('description', JSON.stringify({ 'sdp':client.localDescription }))
})
}, function (err)
{
console.log('error: ' + err)
})
}, function(err)
{
console.log('error: ' + err)
})
})
addStream()
})
function createOffer ()
{
if(!client) { return; }
client.createOffer(function (description)
{
console.log(description)
client.setLocalDescription(description, function ()
{
socket.emit('description', JSON.stringify({ 'sdp': client.localDescription }))
console.log('set local description')
})
})
}
function candidate (message)
{
if(message.candidate)
{
console.log('candidate')
client.addIceCandidate(new RTCIceCandidate(message.candidate))
}
}
function addStream ()
{
navigator.webkitGetUserMedia({audio: true, video: false}, function(stream)
{
client.addStream(stream)
})
}
And my signalling part of my server as it currently stands:
io.on 'connection', (socket) ->
socket.on 'description', (data) ->
parsed = JSON.parse data
socket.broadcast.emit 'description', parsed
socket.on 'candidate', (candidate) ->
parsed = JSON.parse candidate
socket.broadcast.emit 'candidate', parsed
I'd appreciate any insight into this. Thanks.
The "PeerConnection" as the name indicates can be used with only one other peer. You cannot cache the offer SDP generated by one PeerConnection instance to use it with more than one other peers.
In your case, you must create a PeerConnection for each browser that you want to send/receive audio and video from and then exchange the corresponding SDP offer and answers with those browsers via your signaling mechanism.
Please feel free to go through some of the links I have mentioned here to understand how WebRTC works.