Why do I get the error message "Unable to get property 'done' of undefined or null reference" when I run the following code?
new WinJS.Promise(initFunc).then(function () {
/* do something that returns a promise */
}).done(function () {
/* do something that returns a promise */
}).then(function () {
/* do something that returns a promise */
}).done(function () {
});
You can only call done() once in a promise chain, and that must be at the end of the chain. In the problematic code, the done() function is called twice in the promise chain:
new WinJS.Promise(initFunc).then(function () {
}).done(function () { <====== done() is incorrectly called here--should be then()
}).then(function () { <====== the call to then() here will throw an error
}).done(function () {
});
This problem scenario can happen when your code starts off with two separate promise chains and you end up combining them together at some later point, as follows:
new WinJS.Promise(initFunc).then(function () {
/* do something that returns a promise */
}).done(function () { <====== change this done() to a then() if you combine the two
}); promise chains
new WinJS.Promise(initFunc).then(function () {
/* do something that returns a promise */
}).done(function () {
});
You would get the same error simply on:
new WinJS.Promise(initFunc).then(function () {
}).done(function () {
});
because your code in then didn't return a promise on which to call done on.
new WinJS.Promise(initFunc).then(function () {
// Return a promise in here
// Ex.:
return WinJS.Promise.timeout(1000);
}).done(function () {
});
And to come back to your initial code, as you mentioned in your answer you shouldn't chain multiple done together.
Related
I have a very simple two methods in Vuejs and it returns me promise pending what I am doing it's this:
TotalIncomeData(day, branch_office_id) {
return fetch('/api/collection/total/'+day+'/'+branch_office_id+'?api_token='+App.apiToken)
.then(response => {
return response.data;
}
);
},
getTotalIncomes(day, branch_office_id) {
console.log(this.TotalIncomeData(day, branch_office_id))
},
Why am I not getting the value? Thanks
You need to call .json() on the fetch response, and await the result.
And you need to make your function async and await the promise from the first function.
TotalIncomeData(day, branch_office_id) {
return fetch(...).then(rawResponse => rawResponse.json())
^^^^^^
},
async getTotalIncomes(day, branch_office_id) {
^^^^^
console.log(await this.TotalIncomeData(day, branch_office_id))
^^^^^
},
i am doing testing, i made a test in that test i create a mock for a fake function
jest.mock('#/services/myService', ()=>({getAvailables: jest.fn().mockReturnValue()}))
that function is running in my component
onMounted(async () => {
const answer = await getAvailables1()
const answer = await getAvailables2()
const answer = await getAvailables3()
but still i am getting this error
(node:81921) UnhandledPromiseRejectionWarning: TypeError: (0 , _ContractService.getAvailables1) is not a function
(node:81921) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag
if i put like this first getAvailables2
onMounted(async () => {
const answer = await getAvailables2()
const answer = await getAvailables1()
i am getting this error
(node:81921) UnhandledPromiseRejectionWarning: TypeError: (0 , _ContractService.getAvailables2) is not a function
if i put like this first getAvailables3
onMounted(async () => {
const answer = await getAvailables3()
const answer = await getAvailables2()
i am getting this error
(node:81921) UnhandledPromiseRejectionWarning: TypeError: (0 , _ContractService.getAvailables3) is not a function
also i try with mockResolvedValue, does not worked
export const getAvailables = async () => {
let response
let error
try {
response = await getData()
} catch (err) {
error = err
throw err
}
return { response, error }
}
It looks like you want a mock partial:
jest.mock('#/services/myService', () => {
const originalModule = jest.requireActual('#/services/myService');
return {
__esModule: true,
...originalModule,
getAvailables1: () => Promise.resolve({ foo: 'bar' }),
getAvailables2: () => Promise.resolve({ foo: 'baz' }),
getAvailables3: () => Promise.resolve({ foo: 'bad' }),
/* any other method of your service that gets called */
};
});
This will mock the provided functions in the mock while the rest of the service will function as in the original.
getAvailables() is async function that always returns a promise.
So, in order to mock that function you need to return the mock promise with success or rejected value.
Following is the example of mocking that function which returns success promise.
jest.mock('#/services/myService', () => ({
getAvailables: jest.fn().mockResolvedValue(true)
}))
I have the following code:
fooService.update(this.bar).then( this.$emit('updated', this.updatedBar),).catch(err => {...
If an error is encountered, then the error is not caught. If I change the code to be:
fooService.update(this.bar).then(x => {this.$emit('updated', this.updatedBar);}).catch(err => {...
Then the error is caught and shows as expected. Can anyone explain to me what is going on and why it behaves in that way?
Edit
Underlying service code:
function updateBar(bar) {
return $http.put(`/api/bar/${bar.Id}`, bar);
}
So I still think the error is happening in the this.$emit the reason why, in
fooService.update(this.bar).then( this.$emit('updated', this.updatedBar),).catch(err => {
It has to evaluate the this.$emit first as you're setting the response from that function as the .then and not the call itself.
Proof of it doing that
function emit(){
console.log('emit')
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(emit()).catch( function() {console.log('carry on');})
notice how it logs "emit" first
Now if that errors you can see it doesn't hit the catch
function emit(){
console.log('emit')
throw new Error("bad")
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(emit()).catch( function() {console.log('carry on');})
So under the hood it's doing this (the simplest way I can think of)
emit()
try{
getService()
} catch{
...
}
Whereas if you actually pass the .then a function it changes the order of things
function emit(){
console.log('emit')
throw new Error("bad")
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(() => {emit()}).catch( function() {console.log('carry on');})
and again under the hood it looks like this
try{
getService()
emit()
} catch{
...
}
I'm wondering if is it possible, how can I use Vue.js data in my Created() function.
I'll show some code so you can see why I say.
data (){
return {
model: {},
foo: 'boo'
}
},
created (){
const getModel = () => {
const modelId = this.$route.params.id
axios.get('/api/model', { params: {modelId: modelId}})
.then(res => {
this.model = res.data
this.boo = 'hello'
console.log(this.model)
console.log(this.foo)
})
.catch(err => console.log(err))
}
getModel()
const init = () =>{
console.log(this.model)
console.log(this.foo)
}
init()
The first console.log(foo) returns 'hello'.
The second one (init) returns 'boo'.
Also the first console.log(this.model) is what I expect to get but once is out of the axios method it's like empty again all over the mounted function.
I've tried a lot of things but none of them worked, hope I get a solution... Thanks in advance!
As soon as JS functions are non-blocking - your axios call isn't done (model is still empty) when you call for init
Define init as components method
Call this.init() in axios.get callback
It might have to do with the fact that in your created hook you're creating a function using the function keyword, which means your init function will have its own context(its own this).
A solution to this problem would be to use an arrow function.
data () { return { foo: 'bar' } }
created () {
const init = () => {
console.log(this.foo);
}
init(); // bar
}
More about arrow functions
UPDATE
Actually, the issue stems from not awaiting for getModel. Because you are making a request, you first need to wait for the promise to resolve, and then use its resolved data in the code that depends on it.
The async/await version would be:
async created () {
const getModel = async () => {
const modelId = this.$route.params.id
try {
const res = await axios.get('/api/model', { params: {modelId: modelId}})
this.model = res.data
this.boo = 'hello'
console.log(this.model)
console.log(this.foo)
} catch (err) {
console.error(err)
}
}
const init = () =>{
console.log(this.model)
console.log(this.foo)
}
// An async function always returns a promise
await getModel();
init();
}
I am trying to write a test using mocha and chai for my observable methods that makes a call to a server and returns some json data. However, when I run the test I get the following error:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
Even when I overwrite the default timeout time, I still get the above error. What am I doing wrong ?
describe("some test", () => {
let someClass: SomeClass;
before(() => {
someClass = new SomeClass();
});
;
it("should meet some condition", done => {
let getData = someClass.getData('query')
getData.subscribe(json => {
json.success.should.equal(true);
done();
},
done
);
});
});
I found a solution, I call done() in the before hook and the set timeout on each it() function.
describe("some test", () => {
let someClass: SomeClass;
before((done) => {
someClass = new SomeClass();
done();
});
;
it("should meet some condition", done => {
let getData = someClass.getData('query')
getData.subscribe(json => {
json.success.should.equal(true);
done();
},
done
);
}).timeout(10000);
});