How do I add a property to a wrapper of a decorator? - decorator

I do not really get how i can add a property to a wrapper of a decorator function (see the last line for the property that is expected)
Here is the code without the property:
function decorator(f , ms) {
let timeout;
function wrapper(...args) {
clearTimeout(timeout);
if (!timeout) {
f.apply(this , args);
}
timeout = setTimeout(() => {
f.apply(this , args);
}, ms);
}
return wrapper;
}
const sendSignal = (signalOrder , delay) => console.log("Signal sent", signalOrder, delay);
const upgradedSendSignal = decorator(sendSignal, 2000);
setTimeout(() => upgradedSendSignal(1 , 0));
setTimeout(() => upgradedSendSignal(2, 300), 300);
setTimeout(() => upgradedSendSignal(3, 900), 900);
setTimeout(() => upgradedSendSignal(4, 1200), 1200);
setTimeout(() => upgradedSendSignal(5, 2300), 2300);
setTimeout(() => upgradedSendSignal(6, 4400), 4400);
setTimeout(() => upgradedSendSignal(7, 4500), 4500);
setTimeout(() => console.log(upgradedSendSignal.count), 7000); // here i need to use a property of a decorated function (.count) which is supposed to count all the Signals`
Is it supposed to look something like this? If so, I'm confused about the arguments to be used in the function. How do I use the result of the decorator here?
wrapper.history = [];
wrapper.count = function() => {
wrapper.history.push();
return wrapper.history.length;
}

Related

firebase.notifications().onNotificationOpened called multiple times

I called firebase.notifications().onNotificationOpened on componentDidMount and removing it on componentWillUnmount() But seems like it never removes it as its registered multiple time when the app is removed from the background. Below is the code I used, Let me know what I'm doing wrong.
notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: any) => {
console.log("onNotificationOpened", notificationOpen);
notificationOpen && notificationOpen.notification && notificationOpen.notification._data && notificationOpen.notification._data.extra && setTimeout(() => {
}, 500);
});
async componentDidMount() {
this.notificationOpenedListener =
firebase.notifications().onNotificationOpened((notificationOpen: any) => {});
}
componentWillUnmount() {
this.notificationOpenedListener();
}

shouldn't I dispatch an action inside a .then statement?

I found a code on git which I'm trying to understand and in the code the guy have this function:
export function startAddTodo(text) {
return (dispatch, getState) => {
const UID = firebase.auth().currentUser.uid;
const todo = {
text,
isDone: false,
isStarred: false
};
const todoRef = firebaseRef.child(`todos/${UID}`).push(todo);
dispatch(addTodo({
id: todoRef.key,
...todo
}));
todoRef.then(snapshot => {
return;
}, error => {
Alert.alert(JSON.stringify(error.message));
});
};
}
Why shouldn't it be like
const todoRef = firebaseRef.child(`todos/${UID}`).push(todo);
todoRef.then(snapshot => {
dispatch(addTodo({
id: snapshot.key,
...todo
}));
})
I think this because the promise may be rejected, but in the first code he may get an error when trying to call todoRef.key inside the dispatch method.

Ionic 3 File-Transport multipart/form-data

i am actually working on a mobile app in ionic v3 with angular5
The goal is to be able to take a picture or choose from existing ones and then upload it to the server. The first part is done, but i am struggling with the upload.
The api needs multipart/form-data which must consist of two requests. First with text part and second is the image.
Is there any solution for this?
This is what I have done for similar requirement
takePhoto() {
this.camera.getPicture({
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.CAMERA,
encodingType: this.camera.EncodingType.PNG,
saveToPhotoAlbum: true
}).then(imageData => {
this.myPhoto = imageData;
this.uploadPhoto(imageData);
}, error => {
this.functions.showAlert("Error", JSON.stringify(error));
});
}
selectPhoto(): void {
this.camera.getPicture({
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
destinationType: this.camera.DestinationType.FILE_URI,
quality: 100,
encodingType: this.camera.EncodingType.PNG,
}).then(imageData => {
this.myPhoto = imageData;
this.uploadPhoto(imageData);
}, error => {
this.functions.showAlert("Error", JSON.stringify(error));
});
}
private uploadPhoto(imageFileUri: any): void {
this.file.resolveLocalFilesystemUrl(imageFileUri)
.then(entry => (<FileEntry>entry).file(file => this.readFile(file)))
.catch(err => console.log(err));
}
private readFile(file: any) {
const reader = new FileReader();
reader.onloadend = () => {
const formData = new FormData();
const imgBlob = new Blob([reader.result], { type: file.type });
formData.append('evaluationID', this.currentEvaluation.evaluationId);
formData.append('standardID', this.currentEvaluation.id);
formData.append('score', this.currentEvaluation.score);
formData.append('comment', this.currentEvaluation.comment);
formData.append('file', imgBlob, file.name);
this.saveStandard(formData);
};
reader.readAsArrayBuffer(file);
}
And here is code for provider
saveStandard(receivedStandardInfo:any){
return new Promise((resolve, reject) => {
this.http.post(apiSaveStandard,receivedStandardInfo)
.subscribe(res => {
resolve(res);
}, (err) => {
console.log(err);
reject(err);
});
}).catch(error => { console.log('caught', error.message); });
}

Conditionally fetching data in epic

Say I have the following epic:
const getPostsEpic = (action$, store) => {
return action$.ofType(actionTypes.REQUEST_POSTS)
.switchMap(action =>
ajax.getJSON(`api/posts?key=${action.key}`)
.map(response =>
receivePosts({type: RECEIVE_POSTS, posts: response})
).takeUntil(
action$.ofType(actionTypes.ABORT_GET_POSTS)
)
};
and say my reducer is something like
function reducer(
state = {
isFetching: false,
didInvalidate: true,
items: []
},
action
) {
switch (action.type) {
case INVALIDATE_POSTS:
return Object.assign({}, state, {
didInvalidate: true
})
case REQUEST_POSTS:
return Object.assign({}, state, {
isFetching: true,
didInvalidate: false
})
case RECEIVE_POSTS:
return Object.assign({}, state, {
isFetching: false,
didInvalidate: false,
items: action.posts,
})
default:
return state
}
}
I want to make sure that posts are only fetched if my state's didInvalidate === true, is there a good way to make this work with my epic? Could do something like this, but it's not that pretty IMO:
const getPostsEpic = (action$, store) => {
return action$.ofType(actionTypes.REQUEST_POSTS)
.switchMap(action => {
const state = store.getState();
if (state.didInvalidate) {
return ajax.getJSON(`api/posts?key=${action.key}`)
.map(response =>
receivePosts({type: RECEIVE_POSTS, posts: response})
).takeUntil(
action$.ofType(actionTypes.ABORT_GET_POSTS)
)
else {
return Observable.of({type: RECEIVE_POSTS, posts: state.items});
}
}
};
Btw, I'm using this with React. I'm sure this is a pretty common problem, so maybe there's a better way of handling this outside my epics?
You can use if for branching, like this:
const mockAjax = () => Promise.resolve({posts: [4, 5, 6, 7]});
const fetchPost = (action$) => Rx.Observable.fromPromise(mockAjax())
.map(({posts}) => ({type: RECEIVE_POSTS, posts}))
.takeUntil(action$.ofType(ABORT_GET_POSTS))
const defaultPosts = (action$, store) => Rx.Observable.of({type: RECEIVE_POSTS, posts: store.getState().items});
const getPostsEpic = (action$, store) =>
action$.ofType(USER_REQUEST)
.mergeMap(() => Rx.Observable.if(
() => store.getState().didInvalidate, // condition
fetchPost(action$), // if true
defaultPosts(action$, store) // if false
)
.do(x => console.log(x))
)
Check the demo in her: http://jsbin.com/jodaqopozo/edit?js,console,output
Clicking valid/invalid button and then click 'Post Request' will log different value.
Hope this helps.

Nested promoses, not waiting for the result

I have a getProgrammeWrapper method that returns a promise. However in .then method i have few other promises that i will like to execute before returning the programmeWrapper[]
This is service.ts
I am calling the service in ngOnInit
this.service.getProgrammesByWrapper().then(((res) => {
this.programmes = res;
this.result.updateInfo("Sorting classes...")
this.programmes =this.programmes.sort((a,b) => {
return b.programme.click - a.programme.click;
});
this.result.updateSuccess(true);
}));
I hope i have explained the issue clearly. I have tried using await, but it doesn't work as expected.
getProgrammeWrapper()
getProgrammesByWrapper(): Promise<ProgrammeWrapper[]> {
var current = this;
var programmesDTO = new Array<ProgrammeWrapper>();
var table = this.client.getTable("programme");
return new Promise((resolve, reject) => {
table.read()
.then(function (modules) {
modules.forEach(element => {
var newProgDTO = new ProgrammeWrapper(element);
current.getLessonsByProgrammeId(element.id).then(lessons => newProgDTO.lesson = lessons).catch(err => console.log(err));
current.getUser(element.tutorId).then(user => newProgDTO.tutor = user).catch(err => console.log(err));
programmesDTO.push(newProgDTO)
});
resolve(programmesDTO)
}, function (error) { reject(error) });
});
}
I'm not sure it would work, could have bugs too. Try this:
getProgrammesByWrapper(): Promise<ProgrammeWrapper[]> {
var current = this;
var programmesDTO = new Array<ProgrammeWrapper>();
var table = this.client.getTable("programme");
return new Promise((resolve, reject) => {
table.read()
.then(function (modules) {
let promises = new Array<Promise<any>>();
modules.forEach(element => {
var newProgDTO = new ProgrammeWrapper(element);
let promise = current.getLessonsByProgrammeId(element.id)
.then(lessons => newProgDTO.lesson = lessons)
.catch(err => console.log(err));
promises.push(promise);
promise = current.getUser(element.tutorId)
.then(user => newProgDTO.tutor = user)
.catch(err => console.log(err));
promises.push(promise);
programmesDTO.push(newProgDTO)
});
// Wait for all promises to be ready before resolving
Promise.all(promises).then(function() {
resolve(programmesDTO);
});
}, function (error) { reject(error); });
});
}

Resources