Angular2: How to make several GET requests at once - ajax

With a promise JS library (https://github.com/stackp/promisejs) I can make this:
promise.join([
promise.get('/settings'),
promise.get('/translations'),
promise.get('/main-data')
]).then(function(results) {
console.log(results);
});
Now I need to do this with Angular2. So I made a service with methods getSettings, getTranslations, etc. - but how do I join them in the component that uses this service ?
(And join them in such way that when and only when all requests finish - I'll run a functionality that uses all the responses?)

You can use the forkJoin operator for this
import {Observable} from 'rxjs/Rx';
//...some code
Observable.forkJoin(
this.http.get('/settings').map((res:Response) => res.json()),
this.http.get('/translations').map((res:Response) => res.json())
)
.subscribe(data => {
console.log(data[0], data[1]);
});

The answer didn't solved the problem, mostly because I didn't understand how to get the data in the component. But it still guided me very well :)
So, here is the final code:
// Service - "AppService.ts":
import {Observable} from 'rxjs/Rx';
export class AppService {
getAllData() {
return Observable
.forkJoin(
this._http.get('/settings').map(res => res.json()),
this._http.get('/translations').map(res => res.json())
)
}
}
// Component - "AppComponent.ts":
import {AppService} from './app.service';
export class AppComponent {
AllData = {};
appService
.getAllData()
.subscribe(
data => {
console.log('Responses from AJAX:');
console.log(data);
this.AllData = JSON.stringify(data)
},
error => alert(error)
);
}

Related

Making multiple socket instances in React with socket.io, each in a namespace

I have a nestjs application which has Websockets integrated with socket.io. Some of the gateways need authentication. So connecting to them without authenticating logs you out. The problem is, I need some of them without authentication, so I managed to figure out that I could use "namespaces" to connect only to specific Gateways.
I specified in the gateways the namespaces like this:
#WebSocketGateway({
namespace: 'tourneys',
...ConfigConstants.WsConfig,
})
export class AuxiliaryGateway
and in gateways that need authentication, I made it like this:
#UseGuards(SocketSessionGuard)
#WebSocketGateway({
namespace: 'matches',
...ConfigConstants.WsConfig,
})
The problem doesn't seem to be on the back-end however. In the front-end, I tried connecting the websockets like this:
import React, { useEffect, useMemo } from "react";
import { io, ManagerOptions, Socket, SocketOptions } from "socket.io-client";
import { SocketContext } from "#lib/context/SocketContext";
import {
ServerToClientEvents,
ClientToServerEvents,
} from "#lib/types/socket/instance";
import { getAuthToken } from "#lib/services/storage/authToken";
export const SocketProvider: React.FC = ({ children }) => {
const options = {
auth: {
token: getAuthToken(),
},
transports: ["websocket"],
timeout: 20000,
reconnectionAttempts: 10,
reconnectionDelay: 1500,
reconnectionDelayMax: 5000,
} as Partial<ManagerOptions & SocketOptions>;
const tourneysSocket: Socket<ServerToClientEvents, ClientToServerEvents> = io(
`${process.env.NEXT_PUBLIC_WSS_HOST}/tourneys `,
options
);
const matchesSocket: Socket<ServerToClientEvents, ClientToServerEvents> = io(
`${process.env.NEXT_PUBLIC_WSS_HOST}/matches `,
options
);
useEffect(() => {
tourneysSocket.on("connect", () => {
console.log("conectado");
});
tourneysSocket.on("disconnect", e => {
console.warn(`- desconectado "disconnect", ${e}`);
});
tourneysSocket.on("exception", e => {
console.error(e);
});
matchesSocket.on("connect", () => {
console.log("conectado");
});
matchesSocket.on("disconnect", e => {
console.warn(`- desconectado "disconnect", ${e}`);
});
matchesSocket.on("exception", e => {
console.error(e);
});
}, [tourneysSocket, matchesSocket]);
const value = useMemo(
() => ({
tourneysSocket,
matchesSocket,
}),
[tourneysSocket, matchesSocket]
);
return (
<SocketContext.Provider value={value}>{children}</SocketContext.Provider>
);
};
I make two instances, one for each namespace. However, these instances they stop emitting to the correct subscribes after some testing. What might be causing this issue? I can't figure out and I believe it's happening in the front-end. React somehow seems to not use the sockets I'm instatiating after some emits.

How to test nestjs with graphql by end to end?

In the test/posts/posts.e2e-spec.ts file
import { INestApplication } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { Test, TestingModule } from '#nestjs/testing';
import request = require('supertest');
import { PostsModule } from '../../src/posts/posts.module';
describe('Posts (e2e)', () => {
const posts = {
id: 1,
name: 'FirstPost #1',
};
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
...
}),
PostModule,
],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
await app.close();
});
describe('post', () => {
it('should retrieve all post data', async () => {
request(app.getHttpServer())
.post('/graphql')
.send({
query:
`{findPosts() {
name
}}`,
})
.expect(200)
.expect((res) => {
console.log(res.body.data)
expect(res.body.data.post.length).toEqual(posts.length)
})
})
})
});
I created migration and inserted data into database first, then run this test, it can't go to the expect items. Even set console log I can't see anything in the output.
So maybe the /graphql can't be access in this way? I can access the endpoint from browser as http://localhost:3000/graphql.
If import supertest as
import * as request from 'supertest';
In the line request it showed:
This expression is not callable. Type ‘typeof supertest’ has no call signatures.
The version of them:
supertest: 6.1.3
#types/supertest: 2.0.11
Check out this very useful link https://github.com/jmcdo29/testing-nestjs/tree/main/apps/graphql-sample. It explains a lot of things regarding tests including graphql nestjs testing along with sample application

How to map http request observable result to new http observable and return both outer and inner values?

I would like to returns an observable that return two values (in an array or dict) where one value is a conditional http request of the first.
Taking the example from https://coryrylan.com/blog/angular-multiple-http-requests-with-rxjs, I would like to modify the following:
import { Component } from '#angular/core';
import { Http } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/map';
#Component({
selector: 'app-root',
templateUrl: 'app/app.component.html'
})
export class AppComponent {
homeworld: Observable<{}>;
constructor(private http: Http) { }
ngOnInit() {
this.homeworld = this.http.get('/api/people/1')
.map(res => res.json())
.mergeMap(character => this.http.get(character.homeworld))
}
}
So the observable will return both the homeworld and(!) the character.
Use can use resultSelector function of switchMap operator that takes inner and outer observable and you combine them together.
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-switchMap
Here is an example:
Rx.Observable.of(1)
.switchMap(x=>Rx.Observable.of(x+1), (outer, inner) => ({outer, inner}))
.subscribe(x=>console.log(x))
It will print
{
inner: 2,
outer: 1
}
Inside of the mergeMap operator you could manipulate the outer observable (source) and combine it with the inner one by means of a resultSelector:
const example = Rx.Observable.of('Hello')
.mergeMap(v => Rx.Observable.of(v +" Rxjs"),(valueFromSource,valueFromInner)=>{
return `Source: ${valueFromSource}, Inner: ${valueFromInner}`;
});
//output: "Source: Hello, Inner: Hello Rxjs"
const subscribe = example.subscribe(val => console.log(val));
You can check a live example here
More information about mergeMap can be found here

Update method in mutation not running

I have the following component that mutates data. Apollo provides functionality to update the store automatically. I would like to control the way the data is added to the store using the update function. The documentation is straightforward enough, but I can't get it working. What is wrong in the code below that would prevent the console.log from printing.
import React from 'react'
import { connect } from 'react-redux';
import { graphql, gql, compose } from 'react-apollo';
import { personCodeSelector } from '../../selectors/auth';
import UploadBankStatement from '../../components/eftFileUploads/UploadBankStatement.jsx';
const createEftFileUpload = gql`mutation createEftFileUpload(
$bankAccountCode: String!,
$uploadInput: UploadInput!,
$uploadedByPersonCode: String!) {
createEftFileUpload(
bankAccountCode: $bankAccountCode,
uploadInput: $uploadInput,
uploadedByPersonCode: $uploadedByPersonCode) {
id
bankAccountCode
fileName
numberOfProcessedItems
numberOfUnallocatedItems
createdAt
status
}
}`;
const mutationConfig = {
props: ({ ownProps, mutate }) => ({
createEftFileUpload: (bankAccountCode, uploadInput) => {
return mutate({
variables: {
bankAccountCode,
uploadInput,
uploadedByPersonCode: ownProps.personCode
},
update: (store, something) => {
console.log("ping");
console.log(store, something);
},
});
}
})
};
const mapStateToProps = state => {
return {
personCode: personCodeSelector(state)
};
};
export default compose(
connect(mapStateToProps),
graphql(createEftFileUpload, mutationConfig)
)(UploadBankStatement);
Note I have found a couple of similar issues, but it doesn't seem to shed any light on my situation.
Server restart fix my issue. Not sure why this was required with hot-reloading. The code was correct.

Proper Use of Redux-Ovservable ajax http methods: put, delete, post

I'm new to Redux and Redux-Observable. I'm having success in getting information from a rest API with GET and GET(ID), but I cannot get the Delete and Post to work. Sample code below that is issuing a GET request:
[EPIC File]
import { debounceTime, Observable } from 'rxjs';
import { ajax } from 'rxjs/observable/dom/ajax';
import ActionTypes from '../actions/ActionTypes';
import { receiveFeedBack, receiveDeleteFeedBackId,
receiveFeedBackId } from '../actions/FeedBackActions';
export const fetchFeedBack = (action$) => ... Working
export const fetchFeedBackId = (action$) => ... Working
//Not Working
export const deleteFeedBackById = (action$) =>
action$.ofType(ActionTypes.DELETE_FEEDBACK_REQUEST)
.debounceTime(500)
.switchMap(action =>
ajax.delete(`${ActionTypes
.FEEDBACK__URL}/posts/${action.payload.feedbackId}?key=${ActionTypes
.FEEDBACK__API_KEY}`)
.map(receiveDeleteFeedBackId.bind(action))
.takeUntil(action$.ofType(ActionTypes.DELETE_FEEDBACK_CANCELED))
.catch(error => Observable.of({
type: ActionTypes.DELETE_FEEDBACK_ERROR,
payload: error
}))
);
What am I doing wrong?

Resources