How to guarantee code in promise runs first in Javascript? - javascript

function f() {
setTimeout(()=> {
console.log(1);
});
// real situation
// fetch(...).then(()=>{
// console.log(1);
// });
}
function g() {
console.log(2);
}
f();
g();
The actual output is 2, and then 1. Is there any way to guarantee 1, and then 2. Imagine f is a function from other people or a library that I have little control.
My real application is I want to guarantee my code runs after code in a promise in a function is run.

function f() {
return new Promise(resolve => {
resolve(1)
}).then(value=>{
console.log(value)
})
}
function g() {
console.log(2);
}
const run = async () => {
await f();
g();
}
run();

Related

Chain of promises in javascript with ajax calls

I have a function (f1) which I want to get called only after two ajax calls (say a1 and a2) are done. a2 should be called only after a1 is done. Following is the sequence of operation =
$.when(a1 and a2) {
f1
}
I tried the following code snippet -
$.when(a1a2()).done(function(){
f1();
}
var a1a2 = function(){
return $.when(a1()).done(function() {
if (<check for a few variables a1 sets>) {
// another ajax call for which f1 should wait
return a2();
} else {
// random function for which f1 shouldn't wait
f2();
}
});
}
In the above code, f1 is waiting for a1 to finish but it is not waiting for a2 to finish.
I tried the following code snippet as well (but this also just waits for a1 to finish) -
var a1a2 = function(){
var retVal = new Promise(function(){
a1().then(function(){
if (<check for a few variables a1 sets>) {
return a2();
} else {
// random function for which f1 shouldn't wait
f2();
}
});
});
}
I have looked at other similar questions but an not able to devise a solution. Can someone please help?
First of all, your Promise code is faulty, because you're not creating a Promise correctly
new Promise(function(resolve, reject) {
// in here you call resolve or reject otherwise Promise is forever pending
});
However, since a1 returns a Promise (as do all the functions, I'm assuming) you don't need to create a promise
So, your code would be
a1()
.then(function() {
if (somecondition == true) {
return a2();
} else {
f2(); // since there's no return here, there's no "wait" for the promise f2 returns
}
})
.then(function() {
return f1();
})
To illustrate the above, here's your code once with condition true, and then with condition false
Take note of the "time stamps" for the console output
// dummy code to set up some promises
const dummy = (x, d=1000) => {
console.log(performance.now(), 'start', x);
return new Promise(resolve => setTimeout(() => {
console.log(performance.now(), 'end', x);
resolve(x);
}, d));
};
const a1 = () => dummy('a1');
const a2 = () => dummy('a2');
const f1 = () => dummy('f1');
const f2 = () => dummy('f2', 3000);
// end dummy code
console.log('wait for a2');
a1()
.then(function() {
if (true) {
return a2();
} else {
// random function for which f1 shouldn't wait
f2();
}
})
.then(function() {
return f1();
})
.then(() => {
console.log('dont wait for f2');
a1()
.then(function() {
if (false) {
return a2();
} else {
// random function for which f1 shouldn't wait
f2();
}
})
.then(function() {
f1();
});
});
However! If f2 is a function that has no asynchrony then there is no way * to prevent f1 from being called after f2 finish - because that's how javascript works
* - I guess you could put it in a setTimeout, then f2 would execute after f1 begins (again, assuming f1 has some asynchrony, otherwise f2 would begin after f1 ends)
Call a1 to get its Promise, then call Promise.all on a1 and a1 chained with a2:
const a1Prom = a1();
Promise.all([
a1Prom,
a1Prom.then(a2)
])
.then(f1);
console.log('script start');
const delay = ms => new Promise(res => setTimeout(res, ms));
const a1 = () => delay(1000).then(() => console.log('a1 done'));
const a2 = () => {
console.log('a2 starting');
return delay(1000).then(() => console.log('a2 done'));
};
const f1 = () => console.log('f1 starting');
const a1Prom = a1();
Promise.all([
a1Prom,
a1Prom.then(a2)
])
.then(f1);
I'm not familiar with the when/done syntax, but this is a correction for your second snippet. A big hint I would give is that using new Promise is 90% of the time a bad idea.
var a1a2 = function(){
var retVal = a1().then(function(){
if (<check for a few variables a1 sets>) {
return a2();
} else {
// random function for which f1 shouldn't wait
f2();
}
});
});
function a1() {
return new Promise(resolve => {
resolve();
});
}
function a2() {
return new Promise(resolve => {
resolve();
});
}
function f1() {
// this runs when the a1 and a2 is resolved.
}
// this is the call method. there are so many approach in your question first is chaining of promise.
function CallMethod(){
a1().then(function () { // you can optionally pass data here via the resolve in the promise
return a2();
}).then(function () { // same here you can pass optional data here.
// here the a1 and a2 is resolved you can call the f1() now.
f1();
});
}
// second one is called Promise.all()
function CallMethod() {
Promise.all([a1(), a2()]).then(data => { // this is the optional data passed in the resolve base on the index of the function promises.
var firstResolve = data[0]; // resolved data of a1();
var secondResolve = data[1]; // resolved data of a2();
})
}

How to call two async functions every `n` and `m` seconds within a `while (true)` loop?

I have the following loop:
while (true) {
await f();
await g();
}
where f and g are defined as follows:
async function f() {
await Promise.all([SOME_REQUEST_F, sleep(1000)])
}
async function g() {
await Promise.all([SOME_REQUEST_G, sleep(5000)])
}
Also sleep is defined as follows:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
My intention is to have SOME_REQUEST_F awaited every one second, and SOME_REQUEST_G awaited every five seconds, hence wrapping them in f and g.
However, currently g is blocking the re-awaiting of f within the loop.
How to define sleep, such that if used in g, it blocks re-execution of g, but not that of f? Is there a better way to do what I want?
Use two while loops instead:
(async () => {
setTimeout(async () => {
while (true) {
await f();
}
});
while (true) {
await g();
}
})();
The setTimeout there is needed to allow both whiles to run concurrently, so that the initialization of one doesn't block the other from starting.

How to call a different function after completion of one function?

I have written long code, trying to replicate the situation in simple form by this simple code.
What I want to do is after function A() completion, call function B().
I am trying with callback function but in this case, B fired early.
Please suggest how can I write this callback or any other approach?
function A(callback){
a()
function a() {
setTimeout(aa,1000)
function aa(){
console.log("in aa")
}
}
b()
function b() {
setTimeout(bb,100)
function bb(){
console.log("in bb")
}
}
c()
function c(){
setTimeout(cc,50)
function cc(){
console.log("in cc")
}
}
callback();
}
function B() {
console.log("in B");
}
A(B)
output
in B
in cc
in bb
in aa
If you want your callback to run after a timeout has finished, then you have to call it when the timeout has finished.
And that means it needs to be at the end of the function you pass to setTimeout.
With your current code, you are setting the countdown on the timeout going and then immediately calling the callback.
function one(callback) {
console.log(1);
function two() {
console.log(2);
callback();
}
setTimeout(two, 250);
}
function three() {
console.log(3);
}
one(three);
Essentially, what's happening here (as you requested) is that you want B to run after A is completed.
There is no need to use "B" as a callback, with async/await.
B will wait till A is completed before it's called.
const b = () => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{resolve("B done")}, 1000);
});
}
const c = () => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{resolve("C done")}, 500);
});
}
const A = async () => {
const bres = await b();
console.log(bres);
const cres = await c();
console.log(cres);
};
const B = async () => {
console.log("done");
}
const app = async() => {
await A();
await B();
};
app();

Is async function a subset of function in JavaScript?

From what I know, async function expression returns an AsyncFunction object.
Does AsyncFunction inherit Function?
Is it okay to use async function in place of function? (e.g. as a callback parameter) If not, what could be a possible pitfall?
An async function is basically just a function that has been automatically converted to return a promise rather than an ordinary value. It can also use await internally as a shorthand for resolving the promise returned by another async function.
Yes. As shown below, it's type is function, and it's an instance of Function.
async function afunc() {
return 3;
}
console.log(typeof afunc);
console.log(afunc instanceof Function);
Yes, you can use it as a callback. MDN shows examples of using async functions with setTimeout.
var resolveAfter2Seconds = function() {
console.log("starting slow promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(20);
console.log("slow promise is done");
}, 2000);
});
};
var resolveAfter1Second = function() {
console.log("starting fast promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(10);
console.log("fast promise is done");
}, 1000);
});
};
var sequentialStart = async function() {
console.log('==SEQUENTIAL START==');
const slow = await resolveAfter2Seconds(); // If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.
const fast = await resolveAfter1Second();
console.log(slow);
console.log(fast);
}
var concurrentStart = async function() {
console.log('==CONCURRENT START with await==');
const slow = resolveAfter2Seconds(); // starts timer immediately
const fast = resolveAfter1Second();
console.log(await slow);
console.log(await fast); // waits for slow to finish, even though fast is already done!
}
var stillSerial = function() {
console.log('==CONCURRENT START with Promise.all==');
Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then(([slow, fast]) => {
console.log(slow);
console.log(fast);
});
}
var parallel = function() {
console.log('==PARALLEL with Promise.then==');
resolveAfter2Seconds().then((message)=>console.log(message)); // in this case could be simply written as console.log(resolveAfter2Seconds());
resolveAfter1Second().then((message)=>console.log(message));
}
sequentialStart(); // takes 2+1 seconds in total
// wait above to finish
setTimeout(concurrentStart, 4000); // takes 2 seconds in total
// wait again
setTimeout(stillSerial, 7000); // same as before
// wait again
setTimeout(parallel, 10000); // trully parallel
According the the ECMAScript 2017 Language Specification
The AsyncFunction constructor is the %AsyncFunction% intrinsic object and is a subclass of Function.

Async transactions in javascript

First of all rollback is something that I do not care about.
I would like to be able to lock a sequence of async functions/promises/tasks (let's call it a "transaction") with a name/id (or array of names), so that they happen in sequence, and so that any other "transaction" with the same name(s) that are run by another part of the system are delayed from starting until the running transaction using the same name(s) has completed. So it basically is queueing the sequences of async tasks, or "transaction"s.
Here is some example code of the situation:
function a()
{
// do stuff
return new Promise(/*...*/);
}
function b()
{
// do stuff
return new Promise(/*...*/);
}
function c()
{
// do stuff
return a.then(() => b());
}
Now at any time the system could call a, b, or c, and when it does I don't want c and b running at the same time, but obvious c depends on b.
I've been looking for a package on npm to help with this but I haven't found anything, I wonder if anyone can suggest something that I might have missed that would help with this?
I think gulp tasks can help you out of the box. This guarantees that c always run after b and so b after a
const gulp = require('gulp');
gulp.task('a', done => {
// do stuff
console.log('a');
done();
});
gulp.task('b', ['a'], done => {
// do stuff
console.log('b');
done();
});
gulp.task('c', ['b'], done => {
// do more stuff
console.log('c');
done();
});
gulp.start('c'); // Logs a, b, c
Try it!
You could write your own little transaction manager.
const transactions = {};
function doTransaction(name, promiseFunc) {
transactions[name] = (transactions[name] || Promise.resolve()).then(promiseFunc);
}
Use async/await and have babel transpile it. Async Babel Docs
function a()
{
// do stuff
return new Promise(/*...*/);
}
async function b()
{
const aData = await a();
// do stuff
return new Promise(/*...*/);
}
async function c()
{
const bData = await b();
// do stuff
return bData;
}
You can go for https://github.com/Reactive-Extensions/RxJS
They have many functions to handle single/multiple/dependent/parallel async calls.
function a()
{
// do stuff
return new Promise(/*...*/);
}
function b()
{
// do stuff
return new Promise(/*...*/);
}
function c()
{
// do stuff
return new Value;
}
a().then(function(data_a) {
// you can make use of return value (which is data_a) here or as an argument for function b or even function c
b().then(function(data_b) {
// you can make use of return value (which is data_b) here or as an argument for function c
c().then(function(data_c) {
// do your coding here
});
});
});
you can check this link for reference : https://spring.io/understanding/javascript-promises
Ok, here's my take.
You use a wrapper for your function b which returns and object with 2 methods: doCall and wait. The wrapper should be called only once.
doCall will call your function and trace its completion for the wait() function.
wait() will wait for the completion and always resolve when doCall() finishes
Now for the code, also on CodePen (see developer console):
function wrapPromiseFn(fn) {
var prev = null;
var doCall = function() {
var retValue;
prev = new Promise(function(resolve, reject) {
retValue = fn();
retValue.then(function(result) {
resolve(true);
});
retValue.catch(function(result) {
resolve(true);
});
});
return retValue;
};
var wait = function() {
return prev ? prev : Promise.resolve(false);
};
return {
doCall: doCall,
wait: wait
};
}
function a() {
return Promise.resolve(42);
}
function b() {
//return Promise.reject(new Date());
return Promise.resolve(new Date().getTime());
}
var wrappedB = wrapPromiseFn(b);
function doStuff() {
return wrappedB.wait().then(function(didWait) {
return a().then(function(_a) {
return wrappedB.doCall().then(function(_b) {
console.log("didWait, a, b: ", didWait, _a, _b);
});
});
});
}
//run it twice to prove it did wait
doStuff().then(doStuff)
It proves the concept, of course it would need some polish to pass arguments from doCall to the wrapped function.

Categories