How to return a promise from subscribe in angular 5 - angular5

I want to ask that how can we return a promise from the subscribe function.
Here is the code:
A.ts
makeHttpRequest() {
return this.http.get('https://example.com/login');
}
B.ts
class B {
constructor(private a: A) {
this.a.makeHttpRequest().subscribe(data => {
//How to return a promise from here
});
}
}
I have provided a very abstract level of code if someone is facing any issue to understand it please let me know.

I have developed the solution of question asked above:
class B {
constructor(private a: A) {
return new Promise((resolve,reject)=>{
this.a.makeHttpRequest().subscribe(data => {
resolve(true);
}, (err)=> {
resolve(false);
});
});
}
}

Related

How to unit test inner function(not return) of setup in Vue3?

I want to test like this.
Case 1: Error
Cannot spy the inner property because it is not a function; undefined given instead.
Component.vue
export default {
setup() {
function outer() {
inner();
}
function inner() {
// do something for only outer function
}
return { outer };
}
};
Component.spec.js
it('what can I do?', () => {
wrapper.vm.inner = jest.fn(); // throw error
wrapper.vm.outer();
expect(wrapper.vm.inner).toBeCalled();
});
Case 2: Error
Component.vue
export default {
setup() {
function outer() {
inner();
}
function inner() {
// ...
}
return { outer, inner }; // add inner
}
};
Component.spec.js
it('what can I do?', () => {
wrapper.vm.inner = jest.fn();
wrapper.vm.outer();
expect(wrapper.vm.inner).toBeCalled();
});
expect(jest.fn()).toBeCalled()
Expected number of calls: >= 1
Received number of calls: 0
Case 3: Pass
it('what can I do?', () => {
wrapper.vm.outer = jest.fn(() => wrapper.vm.inner());
jest.spyOn(wrapper.vm, 'inner');
wrapper.vm.outer();
expect(wrapper.vm.inner).toBeCalled();
});
This case is not pretty...
Can't I get "inner()" without including it in "return"?
These methods pass when implemented in options api. But I want to use only setup().
Self Answer
I found a way. I made a class like this.
Util.js
class Util {
outer() {
this.inner();
}
inner() {
// do something...
}
}
Component.vue
setup() {
const util = reactive(new Util());
function call() {
util.outer();
}
return { util, call };
}
Component.spec.js
it('is this way correct?', () => {
jest.spyOn(wrapper.vm.util, 'outer');
jest.spyOn(wrapper.vm.util, 'inner');
await wrapper.vm.call();
expect(wrapper.vm.util.outer).toBeCalledTimes(1);
expect(wrapper.vm.util.inner).toBeCalledTimes(1);
});

Vue, await for Watch

i have similar architecture in my app.
computed(){
someStoreValue = this.$store.someStoreValue;
}
watch() {
someStoreValue() = async function () {
//do some async action
}
},
methods: {
someAction() {
this.$store.someStoreValue = 'NEW VALUE'
//await for "watch"
//do stuff
}
}
I need to "someAction" await for "someStoreValue" watcher ends.
I need this kind of architecture someStoreValue can be changed in many places.
Sure, you can't make your watchers async, which is pretty senseless since the data you are after has already arrived.
someStoreValue(newValue, oldValue) {
// But you can still call other async functions.
// Async functions are just functions that returns a promise. Thus:
doSomeAsyncAction().then(this.someAction)
}
Still, why not just do your async stuff in someAction instead?
watch:{
someStoreValue(newValue, oldValue) {
this.someAction()
}
},
methods:{
async someAction(){
await doSomeAsyncStuff() // What prevents you from doing this?
//do stuff
}
}
You can use a flag and wait for it.
data() {
return {
flag: false
}
},
watch() {
someStoreValue() = async function () {
//do some async action
flag = true;
}
},
methods: {
async someAction() {
this.$store.someStoreValue = 'NEW VALUE'
await new Promise((resolve) => {
if (this.flag) {
resolve();
} else {
const unwatch = this.$watch('flag', (newVal) => {
if (newVal) {
unwatch();
resolve();
}
});
}
});
//do stuff
}
}
Maybe in this case the #ippi solution is better, but you can use this approach in other cases.

vue.js1 event not emitting if 4 listerns are registered

I have a very weird issue. I might be doing something very silly here but not aware of it.
I am using vue.js 1. I have a component which is a bootstrap modal that emits 4 custom events. For each of these, I have a listener registered on the parent. The very strange issue is, whenever i am registering the 4th listener, the event that this 4th listener is registered for is not emitting!
// on parent component template...
<fbu-create-maker-commission-modal
v-ref:new-commission-modal
modal-id="addSpCommissionModal"
:show-modal="showCreationModal"
v-on:hiding-modal="onHidingModal"
v-on:sp-commission-created="onCreatingNewSpCommission"
v-on:sp-commission-updated="onUpdatingSpecialCommission"
v-on:sp-commission-remove="onDeletingSpecialCommission"
:modal-template-data="templateData"
:mode="modalLaunchMode"
:object-to-edit="toEditObject"
></fbu-create-maker-commission-modal>
// child component code where the events are emitted from
editCommission() {
let config = Object.assign({}, this.modalTemplateData.httpConfig.updateSpecialCommission, { body: this.form.formData })
this.$http(config).then(response => {
console.log(response);
if(this.isVueResourceResponseValid(response)) {
this.$emit('sp-commission-updated', response.body.data.updatedCommission);
this.handleModalClose();
}
}).catch(errorResponse => {
console.log(errorResponse);
if(errorResponse.status == 422) {
for(errorKey in errorResponse.body) {
this.$set(`form.errors.${errorKey}`, errorResponse.body[errorKey]);
}
}
});
},
deleteCommission() {
let config = Object.assign({}, this.modalTemplateData.httpConfig.deleteSpecialCommission, { body: this.form.formData })
// console.log(config);
this.$http(config).then(response => {
// console.log(response);
if(this.isVueResourceResponseValid(response)) {
console.log('here');
this.$emit('sp-commission-remove', response.body.data.deletedSpecialCommission);
this.handleModalClose();
}
}).catch(errorResponse => {
});
},
createCommission() {
let config = Object.assign({}, this.modalTemplateData.httpConfig.createSpecialCommission, { body: this.form.formData })
this.$http(config).then(response => {
if(this.isVueResourceResponseValid(response)) {
this.$emit('sp-commission-created', response.body.data.newCommission);
this.handleModalClose();
}
}).catch(errorResponse => {
if(errorResponse.status == 422) {
for(errorKey in errorResponse.body) {
this.$set(`form.errors.${errorKey}`, errorResponse.body[errorKey]);
}
}
});
},
It's the sp-commission-remove event that is not being emitted if i register a listner for this on the parent, like this - v-on:sp-commission-remove="onDeletingSpecialCommission"
if i remove this listener, or even change any character of the custome event name, event emitts fine!!
Are there any limit on how many listeners/events can be emitted in Vue1?
It's driving me nuts. Can someone guide me to the right direction pls?

What's the best way to test redux-saga's `all` effect?

I have a saga which currently has a yield all(...) and I'm trying to figure out how to test to see that I'm actually invoking all() with the correct functions. Here's a stripped-down version of what I'm working with:
function* start() {
// I'd prefer not to start the status polling and the listening for
// the cancellation until after the request has been submitted, but
// I'm having trouble figuring out how to do that. So I'm just going
// to listen for 'em all up front here until I'm smarter.
yield all([
waitForCreateRequest(),
waitForPollStatus(),
waitForCancelRequest(),
])
}
function* waitForCreateRequest() {
while ( true ) {
try {
const { payload } = yield take('CREATE_REQUEST')
// ...
} catch ( error ) {
// ...
}
}
}
function* waitForPollStatus() {
while ( true ) {
try {
const { payload } = yield take('POLL_STATUS')
// ...
} catch ( error ) {
// ...
}
}
}
function* waitForCancelRequest() {
while ( true ) {
try {
yield take('CANCEL_REQUEST')
// ...
} catch ( error ) {
// ...
}
}
}
The test that I wrote (using Mocha and bdd-lazy-var) goes something like this:
describe('MySaga', () => {
describe('*start()', () => {
subject(start())
it('calls `all()` with the correct functions', () => {
expect($subject.next().value).to.eql(all([
waitForSubmitExportRequest(),
waitForPollExportStatus(),
waitForCancelExportRequest(),
]))
})
})
})
There is no output--it just hangs...and then I get a "JavaScript heap out of memory" error.
If I console.log($subject.next().value) instead:
describe('MySaga', () => {
describe('*start()', () => {
subject(start())
it.only('foo', () => {
console.log($subject.next().value)
})
})
})
This is what I get:
MySaga
*start()
{ '##redux-saga/IO': true,
ALL:
[ GeneratorFunctionPrototype { _invoke: [Function: invoke] },
GeneratorFunctionPrototype { _invoke: [Function: invoke] },
GeneratorFunctionPrototype { _invoke: [Function: invoke] } ] }
✓ foo
So I'm not sure what's going on here.
Countless Google searches didn't really turn up anything useful, and the closest SO post that I found (how to test redux-saga all effect using jest) was also unhelpful.
Is it a typo that your start function is not a generator function?
Anyway. Can you try to rewrite your start function like this:
function* start() {
yield all([
call(waitForCreateRequest),
call(waitForPollStatus),
call(waitForCancelRequest),
])
}
Now your test could look like:
it('calls `all()` with the correct functions', () => {
expect($subject.next().value).to.eql(all([
call(waitForSubmitExportRequest),
call(waitForPollExportStatus),
call(waitForCancelExportRequest),
]))
})

Relay Mutation keep giving error if static fragments is enabled

Here is my code on my mutation
class CreateUserMutation extends Relay.Mutation {
static fragments = {
user: () => Relay.QL`
fragment on User{
id
email
}
`
}
getMutation () {
return Relay.QL`mutation{ createUser }`
}
getVariables() {
return {
email: 'bondan#something.com'
}
}
getFatQuery() {
return Relay.QL`
fragment on CreateUserPayload {
user{
email
}
}
`
}
getConfigs () {
// console.log('getConfigs props', this.props);
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {
user: this.props.user.id
}
}]
}
}
and this is my implementation on UI
componentWillMount () {
let mutation = new CreateUserMutation();
Relay.Store.commitUpdate(mutation);
}
its a simple experiment apps just to check if my mutation is working when the app load
however the i keep getting this error
user is not defined
Please help me what is wrong with the mutation code?