i am trying to add a number from my firebase realtime database and another number from ionic.
ngOnInit() {
this.number = [50]
}
check(){
firebase.database().ref('users/').once('value', (snapshot) => {
snapshot.forEach(snap => {
this.newlist.push(snap.val().referralCode);
if(this.checking.referralCode == snap.val().referralCode){
console.log('Referral Code Exists')
this.presentAlert();
this.auth.onAuthStateChanged(se => {
this.fire = firebase.database().ref('users/' + se.uid).on('value', resp => {
this.afDB.object('users/'+ se.uid).update({
point: parseInt(this.data.point + this.number),
})
console.log(resp)
})
})
return true;
}
else{
console.log('Invalid')
}
})
})
However the result showed '050505050505050' I have tried using ParseInt() but that does not work.
I think you need to cast this.data.point before sum like below.
point: +this.data.point + this.number
Related
In response to a click handler, i currently perform a:
axios.get("http://whatever.com/itemId").then(response => {
console.log(response);
});
theoretically, a user might click several times extremely quickly in succession. however, I need to process responses in the same order as the requests are made, and these responses are not always ordered.
Can anyone give any pointers?
Came up with the following, which seems to work well. Maybe such a thing should be part of the library itself. Hope others find it useful.
import axios from 'axios';
class OrderedAxios {
constructor() {
this.promises = []
}
get(url) {
var outsideResolve;
var outsideReject;
let promise = new Promise((resolve, reject) => {
outsideResolve = resolve;
outsideReject = reject;
});
promise.resolve = outsideResolve;
promise.reject = outsideReject;
this.promises.push(promise);
axios.get(url)
.then(response => {
promise.response = response;
this.processPromises();
})
.catch(error => {
promise.error = error;
this.processPromises();
})
return promise;
}
processPromises() {
let continueProcessing = false;
do {
continueProcessing = false;
if (this.promises.length) {
let promise = this.promises[0];
if (promise.response || promise.error) {
this.promises.shift();
if (promise.response) {
promise.resolve(promise.response);
} else {
promise.reject(promise.error);
}
continueProcessing = true;
}
}
} while (continueProcessing);
}
}
export default OrderedAxios;
What is the recommended way to map the data to an object and return it as a promise/observable while being able to add dynamic/conditional parameters to the query.
In getCompanies2 I can dynamically add parameters to the query but I can't figure out how to map the data returned to my object and return it as a promise/observable.
In getCompanies everything works as I want it but I have to duplicate the code (as below) if I have dynamic query parameters to add.
Note: convertDocTimeStampsToDate just does what it says. I have excluded it to reduce the size of the code section.
getCompanies(searchText: string, useWhereActive: boolean): Observable<Company[]> {
if (useWhereActive) {
return this.db.collection('companies', ref => ref
.orderBy('name').startAt(searchText).endAt(searchText + '\uf8ff')
.where('active', '==', true)
)
.snapshotChanges()
.pipe(
map(snaps => convertSnaps<Company>(snaps)),
first()
);
} else {
return this.db.collection('companies', ref => ref
.orderBy('name').startAt(searchText).endAt(searchText + '\uf8ff')
)
.snapshotChanges()
.pipe(
map(snaps => convertSnaps<Company>(snaps)),
first()
);
}
}
getCompanies2(searchText: string, useWhereActive: boolean) {
let query = this.db.collection('companies').ref
.orderBy('name').startAt(searchText).endAt(searchText + '\uf8ff');
if (useWhereActive) {
query.where('active', '==', true);
}
query.get().then(querySnapshot => {
const results = this.convertDocuments<Company>(querySnapshot.docs);
console.log(results);
});
}
convertDocuments<T>(docs) {
return <T[]>docs.map(doc => {
return {
id: doc.id,
...doc.data()
};
});
}
export function convertSnaps<T>(snaps) {
return <T[]>snaps.map(snap => {
const data = convertDocTimeStampsToDate(snap.payload.doc.data());
return {
id: snap.payload.doc.id,
...data
};
});
}
I got it to work like below, I guess I am still getting my head around promises.
Any better solutions will be accepted though as I am still learning and don't know if this is the best method.
getCompanies2(searchText: string, useWhereActive: boolean) {
let query = this.db.collection('companies').ref
.orderBy('name').startAt(searchText).endAt(searchText + '\uf8ff');
if (useWhereActive) {
query.where('active', '==', true);
}
return query.get().then(querySnapshot => {
return this.convertDocuments<Company>(querySnapshot.docs);
});
}
I am working in my Ionic Project and my API is getting called 2 times. I am not able to get why my API is getting called 2 times.
This is my productdetails.html:
<ion-col *ngIf="hassizenot && product.out_of_stock == 0" style="padding: 0px;">
<button class="mybtn11" (click)="addtocartnew(product)" ion-button small>
Add to Cart
</button>
</ion-col>
This is my productdetails.ts:
addtocartnew(detailsp)
{
this.storage.get("ID").then((val) =>
{
if(val)
{
if(detailsp.SelectedSize)
{
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
size: detailsp.SelectedSize,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/'+detailsp.id+'/'+val+'/'+detailsp.SelectedSize).subscribe((data) => {
if (data) {
console.log("One");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else{
this.presentToasterror();
}
}
});
}
else
{
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/'+detailsp.id+'/'+val).subscribe((data) => {
if (data) {
console.log("Two");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else{
this.presentToasterror();
}
}
});
}
}
});
}
This is my Service:
usercartproducts(credentials, type) {
var headers = new HttpHeaders();
headers.append('Access-Control-Allow-Origin' , '*');
headers.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
headers.append('Accept','application/json');
headers.append('Content-Type','application/json');
headers.append('Access-Control-Allow-Credentials','true');
headers.append('Access-Control-Allow-Headers','Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
return this.http.post(apiUrl + type, credentials, {headers: headers});
}
In my ts file, I am running the API for adding the products to the cart and it is showing only one response in the console but it is calling 2 times because it is adding the 2 times the product and in the network in the chrome, it is calling 2 times.
Any help is much appreciated.
Just Try This In Your Service:
usercartproducts(credentials, type) {
var headers = new HttpHeaders();
headers.append('Access-Control-Allow-Origin' , '*');
headers.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
headers.append('Accept','application/json');
headers.append('Content-Type','application/x-www-form-urlencoded');
headers.append('Access-Control-Allow-Credentials','true');
headers.append('Access-Control-Allow-Headers','Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
let v = new FormData();
for(var k in credentials)v.append(k,credentials[k]);
return this.http.post(apiUrl + type, v, {headers: headers});
}
This solved my problem.
because you implement yout API twice and your If condition must be wrong
change your ts like this.
addtocartnew(detailsp) {
if (detailsp.SelectedSize) {
this.storage.get("ID").then((val) => {
if (val) {
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
size: detailsp.SelectedSize,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/' +
detailsp.id + '/' + val + '/' + detailsp.SelectedSize).subscribe((data) => {
console.log("One");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else {
this.presentToasterror();
}
}
});
}
})
}
else {
this.storage.get("ID").then((val) => {
if (val) {
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/' +
detailsp.id + '/' + val).subscribe((data) => {
if (data) {
console.log("Two");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else {
this.presentToasterror();
}
}
});
}
})
}
}
change as per your condition and it will work.
I have a problem getting the result from a Cloud Function.
This is my Cloud Function:
exports.retrieveTrips = functions.https.onCall((data, context) => {
const uidNumber = context.auth.uid;
var arrayOfResults = new Array();
var idOfFoundDoc;
var query = admin.firestore().collection('Users').where('UID','==', uidNumber);
query.get().then(snapshot =>
{
snapshot.forEach(documentSnapshot =>
{
idOfFoundDoc = documentSnapshot.id;
});
var queryDoc = admin.firestore().collection('Users').doc(idOfFoundDoc).collection('Trips');
queryDoc.get().then(snapshot =>
{
snapshot.forEach(documentSnapshot =>
{
arrayOfResults.push(documentSnapshot.data());
});
console.log('ARRAY: ' , arrayOfResults);
return arrayOfResults;
})
.catch (err =>
{
console.log ('Error adding document: ', err);
});
})
.catch (err => {
//response.send('Error getting documents', err);
console.log ('Error getting documents', err);
});
And this is the code that I have in my application.
#IBAction func RetrieveTripsButton(_ sender: Any)
{
self.functions.httpsCallable("retrieveTrips").call() {(result, error) in
if let error = error as NSError? {
if error.domain == FunctionsErrorDomain
{
let message = error.localizedDescription
print ("Message: " + message)
}
return
}
print ("Result: -> \(type(of: result))")
print("Result.data type: \(type(of: result?.data))");
print ("Result.data -> \(result?.data)")
}
}
And this is the printed result.
Result: -> Optional<FIRHTTPSCallableResult>
Result.data type: Optional<Any>
Result.data -> Optional(<null>)
The console log is able to print arrayOfResults correctly. Furthermore, when I change this functions to onRequest and feed it the relevant information, the res.status(200).send(arrayOfResults) is able to display the array of JSON in the page.
If I placed the return arrayOfResults; outside of the .then function, I would get a result along with an empty array. My issue is similar to this problem here but I'm unable to receive even that when I return { text: "some_data" }; .
Any help would be great, thank you!
You have to chain the different promises and return the result of the promises chain, as follows.
Note that it is actually what the OP explains in his answer to the SO post you mention "The issue was that I forgot to return the actual promise from the cloud function".
exports.retrieveTrips = functions.https.onCall((data, context) => {
const uidNumber = context.auth.uid;
const arrayOfResults = new Array();
let idOfFoundDoc;
const query = admin.firestore().collection('Users').where('UID','==', uidNumber);
return query.get().then(snapshot => { // here add return
snapshot.forEach(documentSnapshot =>
{
idOfFoundDoc = documentSnapshot.id;
});
const queryDoc = admin.firestore().collection('Users').doc(idOfFoundDoc).collection('Trips');
return queryDoc.get(); // here add return and chain with then()
})
.then(snapshot => {
snapshot.forEach(documentSnapshot => {
arrayOfResults.push(documentSnapshot.data());
});
console.log('ARRAY: ' , arrayOfResults);
return { arrayOfResults : arrayOfResults }; //return an object
})
.catch (err => {
console.log ('Error getting documents', err);
//Here you may return an error as per the documentation https://firebase.google.com/docs/functions/callable#handle_errors, i.e. by throwing an instance of functions.https.HttpsError
});
});
I would also suggest that you look at these two videos from the Firebase team, about Cloud Functions and promises: https://www.youtube.com/watch?v=7IkUgCLr5oA and https://www.youtube.com/watch?v=652XeeKNHSk.
I been working with fileTransfer from Ionic native, it working fine on Android, but on iOS not not do anything at all
Here is my code:
getFile(fileName,url){
let fileTransfer: FileTransferObject = this.transfer.create();
fileTransfer.download(url, this.file.dataDirectory + fileName).then((entry) => {
console.log('entry:',entry)
}, (error) => { console.log(error); });
console.log('file transfer',fileTransfer.onProgress)
var a = fileTransfer.onProgress((progressEvent: ProgressEvent) => {
this.ngzone.run(() => {
console.log(progressEvent.loaded)
});
});
}
it depends on how to derive this.file.dataDirectory.
In my case it always works like this ..
declare var cordova:any; //on top of file
if (this.platform.is('android')) {
this.fsurl = cordova.file.dataDirectory;
}else{
this.fsurl = cordova.file.documentsDirectory;
}