How I can call Observable.complete callback function? It doesn't work - ionic-framework

In ionic 2, (and angularfire2#4.0.0-rc.0, firebase#3.9.0)
I tried this code, but complete function doesn't work!
constructor(public af: AngularFireDatabase, ...) {
this.temp = af.list('/myTest').subscribe(data => {
... // my tastks
}, error => {
console.log(error);
}, () => {
console.log("done!"); // I can't see this output!
});
}
I already tried very many times, but I can't see "done".
In another function, I tried this but the result is same with first.
console.log(this.temp.closed); // false
this.temp.unsubscribe()
console.log(this.temp.closed); // true
,, What can I do..?

AngularFire list and object observables do not complete. Their internal Firebase refs remain connected, listening for changes to the database.
If you want the list to complete after the first value is received, you can use the first operator:
import "rxjs/add/operator/first";
constructor(public af: AngularFireDatabase, ...) {
this.temp = af.list('/myTest')
.first()
.subscribe(data => {
... // my tastks
}, error => {
console.log(error);
}, () => {
console.log("done!");
});
}
Note that complete handlers are not called upon unsubscription. They are called when the observable completes.
If you want a callback to be invoked upon either completion or unsubscription, you can use the finally operator instead:
import "rxjs/add/operator/finally";
constructor(public af: AngularFireDatabase, ...) {
this.temp = af.list('/myTest')
.finally(() => {
console.log("done!");
})
.subscribe(data => {
... // my tastks
}, error => {
console.log(error);
});
}

Related

How can i make the interceptor run a function on error exept for one specific request?

this is my interceptor:
axios.interceptors.response.use(
(response) => {
if (error.response?.status === 403) {
unstable_batchedUpdates(() => {
// to force react state changes outside of React components
useSnackBarStore.getState().show({
message: `${i18n.t('forbidden')}: ${error.toJSON().config.url}`,
severity: 'error',
})
})
}
return Promise.reject(error)
}
)
I want this behavior all the time except when I make this specific call or at least except every head call
export const companiesQueries = {
headCompany: {
name: 'headCompany',
fn: async (companyId) => {
return await axios.head(`/companies/${companyId}`)
},
},
fixed by applying these changes to the api call:
const uninterceptedAxiosInstance = axios.create()
headCompany: {
name: 'headCompany',
fn: async (companyId) => {
return await
uninterceptedAxiosInstance.head(`/companies/${companyId}`)
},
}

How can I write conditional interceptor in Axios

I am able to add an interceptor for the Axios pipeline. Also, I need the loader to be conditional based. The situation is some requests can run in the background and don't need a loader to be blocking the UI. In such cases, I will be able to let the Axios know by sending an extra parameter saying isBackground call. How can I achieve this?
axios.interceptors.request.use((config) => {
this.isLoading = true; // Or trigger start loader
return config
}, (error) => {
this.isLoading = false // Or trigger stoploader
return Promise.reject(error)
})
axios.interceptors.response.use((response) => {
this.isLoading = false // Or trigger stoploader
return response
}, function(error) {
this.isLoading = false // Or trigger stoploader
return Promise.reject(error)
})
Just use your own custom property isBackground on the config like this:
axios.interceptors.request.use((config) => {
console.log(config.isBackground)
return config
}, (error) => {
console.log(error.config.isBackground)
return Promise.reject(error)
})
axios.interceptors.response.use((response) => {
console.log(response.config.isBackground)
return response
}, function(error) {
console.log(error.config.isBackground)
return Promise.reject(error)
})
const config = {
isBackground: true
}
axios.get('https://httpbin.org/get', config)
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
Note that there is a bug in current release 0.19.0 waiting to be fixed, which breaks this functionality. Works ok in version 0.18...
Fiddle

How to pass id to its associated records with Sequelize

I'm building an app with Express on backend, Postgres for db and Sequelize for ORM.
I have 3 associated models:
Post
Event
Publishing, belongs to Post, belongs to Event
When I publish my Post, I update its state to 2, I need to create an Event and Publishing. Publishing will have the postId and eventId, among other things that I'm passing with a query. I tried the following code, it changes the state of the Post, creates an Event and Publishing, but they are not related to each other.
publishPost(req) {
return new Promise((resolve, reject) => {
async.parallel({
changeState: (callback) => {
Post.findAll({
where: { id: req.query.post_id },
attributes: ['id', 'state']
})
.then((updateState) => {
updateState.forEach((postState) => {
postState.updateAttributes({ state: 2 });
});
})
.then((updatedState) => {
callback(null, updatedState);
});
},
createEvent: (callback) => {
Event.create({
instructions: req.query.instructions,
})
.then((createdEvent) => {
callback(null, createdEvent);
});
},
createPublishing: (callback) => {
Publishing.create({
start_date: req.query.startDate,
end_date: req.query.endDate,
})
.then((createdPublishing) => {
callback(null, createdPublishing);
});
}
}, (error, result) => {
resolve(result);
});
});
}
How can I pass the IDs of the two records to the third model?
There are several problems with your implementation!
First of all, your promise never rejects.
Despite of that, you don't actually need to create a promise or use async for this, neither do you want them to run in parallel: If creating a Publishing record needs information about the Event, then you'd want to create first the event, so that you have its id, THEN pass it in the input for the publishing.
Another important thing, take a look at this piece of code:
.then((updateState) => {
updateState.forEach((postState) => {
postState.updateAttributes({ state: 2 });
});
})
.then((updatedState) => {
callback(null, updatedState);
});
Inside the first then, you are making multiple updates, which are promises. They will be dispatched and you never get their values back. Let me explain:
Think if you have just one update to make. It would be like this:
.then((updateStates) => {
return updateStates[0].updateAttributes({ state: 2 });
})
See, we are returning a promise (in this case the update), so the next then will only be called when the update resolves.
If we do this:
.then((updateStates) => {
updateStates[0].updateAttributes({ state: 2 });
})
It will dispatch the update (which takes time) but because you didn't return it, it will pass through and return nothing. Check this out:
var promise1 = new Promise(function(resolve, reject) {
setTimeout(function(){
resolve('foo')
}, 2);
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(function(){
resolve('foo2')
}, 2);
});
promise1
.then(function(result){
promise2
})
.then(function(result){
console.log(result) //will print undefined
})
promise1
.then(function(result){
return promise2
})
.then(function(result){
console.log(result) //will print foo2
})
So, you are calling multiple updates without getting their values back; if they fail, you'd never know.
Just one more thing: if something goes wrong along the way, you probably want to rollback all the changes made so far, for that, you should use transactions.
Maybe you should try something like this (not tested):
return Post.sequelize.transaction(function (t) {
Post.findAll({
where: { id: req.query.post_id },
attributes: ['id', 'state']
})
.then((updatedStates) => {
var promises = []
updatedStates.forEach((postState) => {
promises.push(postState.updateAttributes({ state: 2 }, {transaction: t}));
});
return Promise.all(promises);
})
.then((results) => {
return Event.create({
instructions: req.query.instructions,
}, {transaction: t})
})
.then((createdEvent) => {
return Publishing.create({
post_id: req.query.post_id,
event_id: createdEvent.id, //or event_id, depends on your model
start_date: req.query.startDate,
end_date: req.query.endDate,
}, {transaction: t})
});
}).then(function (result) {
// Transaction has been committed
// result is whatever the result of the promise chain returned to the transaction callback
}).catch(function (err) {
// Transaction has been rolled back
// err is whatever rejected the promise chain returned to the transaction callback
});

Return data in json after subscribe

I am using Angular 5 and want to return data from function getDionaeaResults in json format after subscribing to service
getDionaeaResults(sql) : any {
this.dionaeaService.getDionaeaConnectionLogs(sql).subscribe(res => {
this.data = res;
}),
(error: any) => {
console.log(error);
});
return this.data;
}
After calling this function, this.totalAttacks prints undefined.
getTotalAttack() {
this.totalAttacks = this.getDionaeaResults("some query")
console.log(this.totalAttacks,'attacks')
}
Would suggest using the Obseravable .map() function.
getDionaeaResults(sql) : Observable<any> {
return this.dionaeaService
.getDionaeaConnectionLogs(sql)
.map(res => res);
}
getTotalAttack(sql){
this.getDionaeaResults("some query")
.subscribe(
res => { this.totalAttacks = res; },
err => { console.log(err); }
);
}
this.getDionaeaResults is returning undefined because the service you're calling is asynchronous you have to wait for the subscribe callback. as Observables are asynchronous calls
this.data=res
might execute after the return statement. You can perhaps call that dionaeaService directly inside getTotalAttack() function, like this:
getTotalAttack(sql){
this.dionaeaService.getDionaeaConnectionLogs(sql).subscribe(res => {
this.totalAttacks = res;
}),
(error: any) => {
console.log(error);
});
}

Angular2 rxjs call to rest api and get undefined output

I have problem with my Angular2 service. My function call to rest server, next I would like to print output but console.log shows undefined.
Main class
export class EventListComponent implements OnInit {
events: Event[];
constructor(
private eventService: EventService
) {}
loadPosts() {
console.log('loading');
this.eventService.getEvents()
.subscribe(
events => this.events = events,
err => {
console.log(err);
});
console.log(this.events); // undefined
}
ngOnInit() {
// Load comments
this.loadPosts();
}
}
And EventService
#Injectable()
export class EventService {
private eventsUrl = 'http://localhost:5000/search';
constructor(private http: Http) {}
getEvents(): Observable<Event[]> {
return this.http.get(this.eventsUrl)
.map((res: Response) => res.json())
.catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
}
Whats is wrong?
You're logging this.events before it is set. Do:
loadPosts() {
this.eventService.getEvents()
.catch(err => console.log(err))
.subscribe(
events => {
this.events = events;
console.log(this.events);
});
}