I want to test myFunction(), which is expected to turn var appState from "old state" to "new state". However, myFunction() invokes n functions fetcher() which contain the async function fetch - similar to the psudocode below.
// Application code
myFunction() = function {
for (var i = 0, len = myarray.length; i < len; i ) {
fetcher()
}
}
fetcher = function(){
fetch(url) // Is asynchronous
.then(response => response.json())
.then(data => {
if(data == 'abc'){ appState = "new state" }
}
}
// Test
myFunction()
setTimeout(() => {
assert.equal(appState, "New State")
}, 10);
This timeout works fine and the test passes, but it feels like a code smell. Is there a more correct way to wait for the async functions generated by myFunction() to complete before testing the new state?
CodePudding user response:
async / await is the way to go!
// Application code
myFunction() = async function {
for (var i = 0, len = myarray.length; i < len; i ) {
await fetcher()
}
}
fetcher = async function(){
const respons = await fetch(url) // Is asynchronous
const data = await response.json())
if(data == 'abc'){ appState = "new state" }
}
// Your test now should look like this:
async function test() {
await myFunc()
assert.equal(appState, "New State")
}
test()
async / await is awesome!
CodePudding user response:
You would need to utilize promises or use Async/Await
const fakeFetch = (url) => new Promise((resolve) => {
setTimeout(() => {
resolve({
json: () => new Promise((resolveJSON) => resolveJSON({
myKey: url === 3 ? 'abc' : 'foo'
})),
});
}, Math.ceil(1000 * Math.random()));
});
let appState = 'x';
const myarray = [0, 1, 2, 3, 4];
const myFunction = function() {
var myPromises = [];
for (var i = 0, len = myarray.length; i < len; i ) {
myPromises.push(fetcher(myarray[i]))
}
return Promise.all(myPromises);
// return Promise.allSettled(myPromises);
}
// const myFunction = function() {
// return Promise.allSettled(myarray.map(x => fetcher(x)));
// }
const fetcher = function(url) {
return fakeFetch(url)
.then(response => response.json())
.then(data => {
if (data.myKey == 'abc') {
appState = "new state"
}
});
}
myFunction().then( function () {
console.assert(appState === "New State", "appState", appState);
});
const fakeFetch = (url) => new Promise((resolve) => {
setTimeout(() => {
resolve({
json: () => new Promise((resolveJSON) => resolveJSON({
myKey: url === 3 ? 'abc' : 'foo'
})),
});
}, Math.ceil(1000 * Math.random()));
});
let appState = 'x';
const myarray = [0, 1, 2, 3, 4];
const myFunction = async function() {
for (var i = 0, len = myarray.length; i < len; i ) {
await fetcher(myarray[i])
}
}
const fetcher = async (url) => {
const response = await fakeFetch(url);
const data = await response.json();
if (data.myKey == 'abc') {
appState = "new state"
}
}
const test = async () => {
await myFunction();
console.assert(appState === "New State", "appState", appState);
};
test();
