I work with an application which sends some requests to server.
function createAjaxCall(data, done, fail) {
return $.post("process_watch.php", data).then(done).fail(fail);
}
and
function step1() {
return createAjax({ }, function(result) { console.log(result); return result; }, function() { });
}
function step2(res) {
return createAjax({ }, function(result) { console.log(result); return result; }, function() { });
}
...
Some requests take a while (let's assume that I use sleep(1500); in PHP) and if I do:
step1().then((data) => step2(data)).then((data) => step3(data)) then will execute in same time.
What is going wrong ?
There is nothing parallel going on in javascript. It's a concurrent language .What you wrote will be executed serially ( one after another ).It will take 1500*3 ms to finish (assuming each take 500 ms)
step1().then((data) => step2(data)).then((data) => step3(data))
To make them execute concurrently ( a.k.a parallel in js) you should do the following. All the call will be sent out to fetch data.When all of them resolves promise will go to the then-catch chain.It will take more or less 1500 ms to finish ( assuming each takes 500 ms)
Promise.all([step1(),step2(),step3()]).then().catch()
You can use async function
An async function returns a Promise, so you can wait for the sync executions end, and then work with the returned result.
Look this code snippet
function step1() {
return new Promise((resolve) => {
setTimeout(function() {
resolve(1);
}, 1000);
});
}
function step2() {
return new Promise((resolve) => {
setTimeout(function() {
resolve(2);
}, 1000);
});
}
function step3() {
return new Promise((resolve) => {
setTimeout(function() {
resolve(3);
}, 1000);
});
}
async function process() {
var one = await step1();
var two = await step2();
var three = await step3();
/*if (some error) {
return Promise.reject('Some error!');
}*/
return `RESULT: ${one} - ${two} - ${three}`
}
console.log('Waiting results...');
process().then((result) => {
console.log(result);
console.log('DONE!');
}).catch((error) => {
console.log(error);
});
Resource
async function
Promise.reject()
Related
I am testing a function which calls another function that return promise, I have tried with async/await, done and resolves and rejects but nothing work. code -
let total = 0;
function sum(a, b) {
return new Promise((res, rej) => {
setTimeout(() => {
res(a + b);
}, 0)
});
}
function wrapper() {
sum(2,3)
.then(data => {
total = data;
})
.catch(err => {
console.log(err);
})
}
describe('Test', () => {
it('adds 2 + 3 to equal 5', () => {
// want to call wrapper and test that total is equal to 5
});
})
I want to call the wrapper function and wait till, then or catch block executes and it stores the data to total, but jest is not waiting for it.
In this simplified example, I am calling three functions when the first promise gets resolved.
var test = new Promise(function (res, err) { setTimeout(res, 3000) })
test.then( () => { console.log("A") });
test.then( () => {
return new Promise(function(res, err) {
setTimeout(()=> { console.log("C");
res() }, 3000)
});
});
test.then( () => { console.log("B") });
The output as expected is A B C.
Let's suppose that I want to invoke the third .then to console B only when the second promise gets resolved.
If I try to store the second promise (myProm) in global and attach a .then function on it, I'll get (reasonably) a TypeError because at compile time myProm is still undefined.
var test = new Promise(function (res, err) { setTimeout(res, 3000) })
var myProm;
test.then( () => { console.log("A") });
test.then( () => {
myProm = new Promise(function(res, err) {
setTimeout(()=> { console.log("C");
res() }, 3000)
})
return myProm;
});
myProm.then( () => { console.log("B") });
How do I proceed? What's the best way to chain two promises together so that the returned Promise obj from one .then needs to get resolved before we can execute the next then.
In this scenario, the output I'd like to have would be A C B
then returns a promise that resolves when the indicated function has run and the value it returned has resolved (this is a slight oversimplification, but sufficient for the task here).
Therefore, to chain a promise on the result of a then. Just tack on another .then:
var test = new Promise(function (res, err) { setTimeout(res, 3000) })
test.then( () => { console.log("A") });
test
.then( () => {
return new Promise(function(res, err) {
setTimeout(()=> { console.log("C"); res() }, 3000);
});
})
.then( () => { console.log("B") });
Each time you call .then, you create a new Promise that resolves when the Promise returned by that .then resolves. You should assign the result of the myProm-containing .then to a variable, and then call .then on that variable:
var test = new Promise(function (res, err) { setTimeout(res, 500) })
var myProm;
test.then( () => { console.log("A") })
.then( () => {
myProm = new Promise(function(res, err) {
setTimeout(()=> { console.log("C");
res() }, 500)
})
return myProm;
})
.then( () => { console.log("B") });
Most of the time when using Promises, you should be chaining .thens like this. Only do prom.then(...) ... prom.then(...) when you want to initialize two completely separate asynchronous operations when the prom resolves.
function renderLoader() {
console.log("Loading");
}
function getResults() {
setTimeout(myTimeout, 3000)
}
function myTimeout() {
console.log("The Results");
}
function clearLoader() {
console.log("Loading over");
}
const controlSearch = async () => {
renderLoader();
await getResults();
clearLoader();
}
controlSearch();
I'm new to async/await. I expected the result of above code to be
Loading //then wait for 3 seconds
Results
Loading over
But instead it produced this,
Loading
Loading over //then wait for 3 secs
Results
I don't understand what I m doing wrong?
await/async play with promises. As is, getResults synchronously returns undefined, while it should return a Promise that await will, well, await:
function getResults() {
return new Promise((resolve) => {
setTimeout(() => {
myTimeout();
resolve();
}, 3000)
});
}
Or:
function getResults() {
return new Promise((resolve) => {
setTimeout(resolve, 3000)
}).then(myTimeout);
}
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await.
This question already has answers here:
ES6 promises with timeout interval
(6 answers)
Closed 5 years ago.
I want to create one Promise that, internally, calls a series of asynchronous methods in sequence and returns the results of these methods, concatenated in an ordered Array, once the last method returns.
I was trying this:
const getArray = function (thisArray) {
return new Promise ( function (resolve, reject) {
if (thisArray.length < 3) {
setTimeout(function() {
console.log('adding element');
thisArray.push(thisArray.length);
getArray(thisArray);
}, 1000);
} else {
console.log(thisArray);
console.log('resolving');
resolve(thisArray);
}
});
}
getArray([]).then(function(data) {
console.log('thened');
console.log(data);
})
but it doesn't ever calls the then(). How can I do this?
You're not far off at all, you just need to be sure to call resolve for each new Promise. If you're still building the array, you pass the resulting promise from your recursive getArray call; otherwise, you pass the array:
const getArray = function(thisArray) {
return new Promise((resolve, reject) => {
if (thisArray.length >= 3) {
// All done
resolve(thisArray);
} else {
// Do something async...
setTimeout(() => {
// ...add the result
console.log('adding element');
thisArray.push(thisArray.length);
// ...and recurse
resolve(getArray(thisArray));
}, 1000);
}
});
}
getArray([]).then(data => {
console.log('done');
console.log(data);
});
That's a bit cleaner if you separate the function doing the async work from getArray, and ensure that the function doing the async work returns a promise. For our purposes, we can just wrap setTimeout in a Promise wrapper:
const setTimeoutP = (cb, delay) => {
return new Promise(resolve => {
setTimeout(() => {
resolve(cb());
}, delay);
});
};
then:
const getArray = thisArray => {
if (thisArray.length >= 3) {
return Promise.resolve(thisArray);
}
return setTimeoutP(() => {
console.log("adding element");
thisArray.push(thisArray.length);
});
};
Live copy:
const setTimeoutP = (cb, delay) => {
return new Promise(resolve => {
setTimeout(() => {
resolve(cb());
}, delay);
});
};
const getArray = thisArray => {
if (thisArray.length >= 3) {
return Promise.resolve(thisArray);
}
return setTimeoutP(() => {
console.log("adding element");
thisArray.push(thisArray.length);
return getArray(thisArray);
}, 1000);
};
getArray([]).then(data => {
console.log('done');
console.log(data);
});
I need to finish some query no sooner than 500ms.
I don't want to waste that 500ms either, like delaying everything like here:
someFunction(someService) {
setTimeout(() => {
getDataFromBackend().then(data => {
someService.makeAnAction();
});
}, 500);
}
How to start getting the data from the backend at once but do something with that data not too soon?
Make a function to get a promise that resolves in the requisite time:
const delay = ms => new Promise(resolve => {
setTimeout(resolve, ms);
});
Wait for both it and your operation to complete:
someFunction(someService) {
return Promise.all([getDataFromBackend(), delay(500)]).then(([data]) => {
someService.makeAnAction();
});
}
Alternative without destructuring, with Bluebird:
someFunction(someService) {
const dataGet = getDataFromBackend();
return delay(500).return(dataGet).then(data => {
someService.makeAnAction();
});
}
Potentially misleading equivalent of the above:
someFunction(someService) {
return delay(500)
.return(getDataFromBackend())
.then(data => {
someService.makeAnAction();
});
}
Async/await:
async someFunction(someService) {
const dataGet = getDataFromBackend();
await delay(500);
const data = await dataGet;
someService.makeAnAction();
}