Traditional way of doing asnyc method in javascript - javascript

I was searching online on how we create the traditional way of doing async function in Javascript but it wasn't available. I have implemented a promise function in my program, however the software that I am using (tableu) to create all custom styling does not support ES5-ES8 and async functions, as this will throw an error, so I was wondering if this is possible.
function promise() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), 500);
})
}
async function result() {
await promise();
}
result().then(render => {
customStyle()
});
All of my code shown is working fine. I'm wondering how can I convert this to the old way of doing async functions. Is this possible or is it only available in ES8?

Callbacks are the non-Promise or async/await way of doing this, and are basically how those things work under the hood.
Here's a simple example by modifying your snippet:
function promise(callback) {
setTimeout(() => callback(), 500);
}
function result() {
promise(callback);
}
function callback() {
customStyle();
};
Instead of result being an async function that you can await elsewhere in your code, it could also take a callback argument, like promise, that you would pass it when it's invoked. The implementation of that callback function would be like the then of an actual Promise.
Now you can see why the Promise API and async/await were such nice improvements to the spec.

To use promises the tradicional way, you have to replace the await and use .then(()=> ...). I'll try to show a snippet here to help you to understood.
The code that you have shown does not need the async or await, it goes well like that
function promise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('resolved')
resolve()
}, 500);
})
}
promise().then(render => {
customStyle()
});
Here i'll show you a code that have a good use of it and then I'll convert it:
function callSomeService() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called')
resolve({ idOfSomething: 1 })
}, 2000);
})
}
function callAnotherServiceUsingTheDataOfThePreviousCall(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called with', data)
resolve(['potato 1', 'potato 2', 'potato 3'])
}, 2000);
})
}
async function result() {
const serviceResponse = await callSomeService();
const arrayOfPotatos = await callAnotherServiceUsingTheDataOfThePreviousCall(serviceResponse);
return arrayOfPotatos.map((potato, index) => `${index} - ${potato}`)
}
result().then(arrayOfPotatos => {
arrayOfPotatos.forEach(potato => console.log(potato))
});
Now I'll convert it to not use async or await, but still using promises.
function callSomeService() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called')
resolve({ idOfSomething: 1 })
}, 2000)
})
}
function callAnotherServiceUsingTheDataOfThePreviousCall(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('service whas called with', data)
resolve(['potato 1', 'potato 2', 'potato 3'])
}, 2000)
})
}
function result() {
return callSomeService().then(serviceResponse => {
return callAnotherServiceUsingTheDataOfThePreviousCall(
serviceResponse
).then(arrayOfPotatos => {
return arrayOfPotatos.map((potato, index) => `${index} - ${potato}`)
})
})
}
result().then(arrayOfPotatos => {
arrayOfPotatos.forEach(potato => console.log(potato))
})
Those two last codes does the same thing, but the second use async and await and the third does not. Async and await are just a syntax sugar to use promises.
I expect that will help you.

Related

How can i synchronize these 3 promise-based functions?

How can i synchronize these 3 promise returning functions (For example in other function)? I want to get following output -> Start -> (2secs)..2..(3secs)..3..(4secs)..4 -> End. I've tryed Generators, but my output wasn't like that (Probably i did something wrong)
function resolveAfter2Seconds() {
new Promise(resolve => {
setTimeout(() => {
resolve('resolved 2');
console.log('2')
}, 2000);
});
}
function resolveAfter3Seconds() {
new Promise(resolve => {
setTimeout(() => {
resolve('resolved 2');
console.log('3')
}, 3000);
});
}
function resolveAfter4Seconds() {
new Promise(resolve => {
setTimeout(() => {
resolve('resolved 2');
console.log('4')
}, 4000);
});
}
First, change the functions to return their promises. For example:
function resolveAfter2Seconds() {
return new Promise(resolve => { // <------ added return statement
setTimeout(() => {
resolve('resolved 2');
console.log('2')
}, 2000);
});
}
Then either chain the promises together
resolveAfter2Seconds()
.then(() => resolveAfter3Seconds())
.then(() => resolveAfter4Seconds());
Or use async/await syntax:
async function exampleFunction() {
await resolveAfter2Seconds();
await resolveAfter3Seconds();
await resolveAfter4Seconds();
}
You might want to try chaining to get the sequential output:
resolveAfter2Seconds()
.then(() => resolveAfter3Seconds())
.then(() => resolveAfter4Seconds())
PS. Don't forget to make those functions return promises.

Changing my callbacks, promise to async await

My code:
Callbacks:
const first = () => {
console.log('first');
};
const second = (callback) => {
setTimeout(() => {
console.log('second');
callback();
}, 2000);
};
const third = () => {
console.log('third');
};
first();
second(third); OUTPUT: 'first', 'second', 'third'
Promises:
const first = () => new Promise((resolve, reject) => {
resolve('first');
});
const second = () => new Promise((resolve, reject) => {
setTimeout(() => {
resolve('second');
}, 2000);
});
const third = () => {
console.log('third');
};
first()
.then((firstPromiseValue) => {
console.log(firstPromiseValue);
second()
.then((secondPromiseValue) => {
console.log(secondPromiseValue);
third();
})
}); OUTPUT: 'first', 'second', 'third'
Promise all:
const first = new Promise((resolve, reject) => {
resolve('first');
});
const second = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('second');
}, 2000);
});
const third = new Promise(function(resolve, reject) {
resolve('third');
});
Promise.all([first, second, third]).then((values) => {
console.log(values);
}); OUTPUT: ['first', 'second', 'third']
Async Await:
How to convert this above code using async await?
Which is the good flow control for javascript applications?
What about some async library which uses methods like async.waterfall, etc..
By the way, is my above code is ok or not?
How to convert this above code using async await?
async/await is not a replacement for promises, it is a replacement for then() and catch(). You'd still be using promises. So you'd take the first, second and third definition from your Promises section, and then:
async function firstSecondThird() {
let firstPromiseValue = await first();
console.log(firstPromiseValue);
let secondPromiseValue = await second();
console.log(secondPromiseValue);
third(); // not a promise, no need to await
}
firstSecondThird();
Which is the good flow control for javascript applications?
Objectively, none of them are better; but async/await is the most readable, callbacks the most explicit (with then code being in the middle).
What about some async library which uses methods like async.waterfall, etc..
Promises generally do everything those libraries do, and also got selected to be standardised. You may forget about those libraries unless you are maintaining old code that requires them.
By the way, is my above code is ok or not?
It seems to do what you want it to do, more or less, without obvious problems in efficiency or legibility. I'd say it's OK.
How to convert this above code using async await?
Using async/await is another way to use Promises. It's most nice visualy because you don't lost in then/catch but you can use it. Here you have two examples. First one with then and second one without.
const first = async (value) => {
return new Promise((resolve, reject) => {
resolve('first ');
});
};
const second = async (value) => {
return new Promise((resolve, reject) => {
resolve(value + 'second ');
});
};
const third = async (value) => {
return new Promise((resolve, reject) => {
resolve(value + 'third');
});
};
first('').then(second).then(third).then( value => console.log(value) );
const first = async () => {
return new Promise((resolve, reject) => {
resolve('first ');
});
};
const second = async () => {
return new Promise((resolve, reject) => {
resolve('second ');
});
};
const third = () => {
return 'third';
};
async function main() {
let firstValue = await first();
let secondValue = await second();
let thirdValue = third();
return firstValue + ' ' + secondValue + ' ' + thirdValue;
}
main()
.then(console.log)
.catch(err => { console.log('Error:', err) });
Which is the good flow control for javascript applications?
Normally when you need to use Promise in the middle of a function or multiple async calls fo functions.
What about some async library which uses methods like async.waterfall, etc..
I don't know about any library to use async/await. Sorry!

JS Promise: control flow

I have to set a few things up via an API. It's important that the different functions are executed after each other. All of the listed functions return a proper promise.
a(analyticsConfig._listConfig)
.then(function() {
return b(listName, analyticsConfig._fieldConfig);
})
.then(function() {
return c(listName)
})
.then(function() {
return d(analyticsConfig._roleConfig);
})
I'd like to use something like a.then(b(listName, analyticsConfig._fieldConfig)) or so but as you probably know this won't work.
Is there another way to do this?
That will only work if b returns a function that returns a promise. You always must pass a function to then as the callback, there's no way around that. There are however many ways to construct one.
Leaving partial application (with bind or other), currying and such stuff aside, your best options for nicer syntax are ES8 async/await
(async function() {
await a(analyticsConfig._listConfig);
await b(listName, analyticsConfig._fieldConfig);
await c(listName);
await d(analyticsConfig._roleConfig);
})();
or ES6 arrow functions:
a(analyticsConfig._listConfig)
.then(() => b(listName, analyticsConfig._fieldConfig))
.then(() => c(listName))
.then(() => d(analyticsConfig._roleConfig))
You can write it as
a.then(b.bind(null, listName, analyticsConfig._fieldConfig))
or, if you're either using babel to transpile your code, or you're targeting a version of node > v4., you can do
a.then(() => b(listName, analyticsConfig._fieldConfig))
You can bind it:
a.then(b.bind(context,listName,analyticsConfig._fieldConfig))
Be sure to bind the expected context to it though.
According to the docs:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
You can do the following using async/await:
function a() {
console.log('Getting A...');
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello A!');
}, 1000);
});
}
function b() {
console.log('Getting B...');
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello B!');
}, 1000);
});
}
function c() {
console.log('Getting C...');
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello C!');
}, 1000);
});
}
function d() {
console.log('Getting D...');
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello D!');
}, 1000);
});
}
async function getAll() {
await a();
await b();
await c();
await d();
console.log('Done');
}

Async function inside Promises

Here is my situation:
fetchData(foo).then(result => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result + bar);
}, 0)
});
}).then(result => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve( result + woo);
}, 0)
});
}).then(result => {
setTimeout(() => {
doSomething(result);
}, 0)
});
Where each setTimeout is a different async operation using the callback pattern.
It is really painfull to wrap each function inside a promise, I feel like the code should look more like this:
fetchData(foo).then(result => {
setTimeout(() => {
return result + bar;
}, 0)
}).then(result => {
setTimeout(() => {
return result + woo;
}, 0)
}).then(result => {
setTimeout(() => {
doSomething(result);
}, 0)
});
Obviously this doesn't work.
Am I using Promises right? Do I really have to wrap all existing async function in promises?
EDIT:
Actually I realize my example was not totally reprensentative of my situation, I did not make it clear that the setTimeout in my example is meant to reprensent en async operation. This situation is more representative of my situation:
fetchData(foo).then(result => {
return new Promise((resolve, reject) => {
asyncOperation(result, operationResult => {
resolve(operationResult);
}, 0)
});
}).then(result => {
return new Promise((resolve, reject) => {
otherAsyncOperation(result, otherAsyncResult => {
resolve( otherAsyncResult);
}, 0)
});
}).then(result => {
doSomething(result);
});
Am I using Promises right? Do I really have to wrap all existing async function in promises?
Yes. Yes.
I feel like the code should look more like this
No, it shouldn't. It rather should look like this:
function promiseOperation(result) {
return new Promise((resolve, reject) => {
asyncOperation(result, resolve, 0)
});
}
function otherPromiseOperation(result) {
return new Promise((resolve, reject) => {
otherAsyncOperation(result, resolve, 0)
});
}
fetchData(foo).then(promiseOperation).then(otherPromiseOperation).then(doSomething);
It is really painfull to wrap each function inside a promise
Well, don't repeatedly write it out every time. You can abstract this wrapping into a function!
function promisify(fn) {
return value => new Promise(resolve => {
fn(value, resolve, 0)
});
}
const promiseOperation = promisify(asyncOperation);
const otherPromiseOperation = promisify(otherAsyncOperation);
fetchData(foo).then(promiseOperation).then(otherPromiseOperation).then(doSomething);
Notice that most promise libraries come with a such a promisification function included, so your whole code reduces to these three lines.
You are using promise right. Just a small note on the first snippet of code: you are not returning a promise from the last then() callback:
...
}).then(result => {
setTimeout(() => {
doSomething(result);
}, 0)
});
This is correct if you need simply to do an async operation without returning to the caller of fetchData the value of the last async operation. If you need to return this value, you need to convert to promise this operation too:
fetchData(foo).then(result => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result + bar);
}, 0)
});
}).then(result => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result + woo);
}, 0)
});
}).then(result => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(doSomething(result));
}, 0)
});
});
Here I suppose doSomething is a sync function returning a value.
Said so, if you want to reduce the noise of create the promise to wrap setTimeout every time, you can create a utility function setTimeoutWithPromise:
function setTimeoutWithPromise(operation, millisec) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(operation());
}, millisec)
});
}
And clean your code:
fetchData(foo)
.then(result => setTimeoutWithPromise(() => result + bar, 0))
.then(result => setTimeoutWithPromise(() => result + woo, 0))
.then(result => setTimeoutWithPromise(() => doSomething(result), 0));

How to structure nested Promises

I have a situation where I think the only choice for me is to nest some Promises within each other. I have a Promise that needs to be performed and a method that does something until that Promise is complete. Something like this:
let promise = new Promise((resolve, reject) => {
// Do some stuff
});
doSomethingUntilPromiseisDone(promise);
However, within my Promise, I need to execute another method that returns another Promise:
let promise = new Promise((resolve, reject) => {
fetchValue(url)
.then((value) => {
// Do something here
}).catch((err) => {
console.error(err);
});
});
doSomethingUntilPromiseisDone(promise);
But now, in the fetchValue method's then statement, I have another method I need to execute that, guess what, returns another Promise:
let promise = new Promise((resolve, reject) => {
fetchValue(url)
.then((value) => {
saveToCache(value)
.then((success) => {
console.log('success!!');
resolve('success');
});
}).catch((err) => {
console.error(err);
});
});
doSomethingUntilPromiseisDone(promise);
So in the end, I have a Promise, within a Promise, within a Promise. Is there someway I can structure this better so that it is more straightforward? It seems like nesting them within each other is counter to Promise's intended chaining approach.
Use .then()
let doStuff = (resolve, reject) => {/* resolve() or reject() */};
let promise = new Promise(doStuff);
doSomethingUntilPromiseisDone(
promise
.then(value => fetchValue(url))
.then(value => value.blob())
.then(saveToCache)
)
.then(success => console.log("success!!"))
.catch(err => console.error(err))
you can use generator to flatten your nested promises (Bluebird.couroutine or Generators)
//Bluebird.couroutine
const generator = Promise.coroutine(function*() {
try {
const value = yield fetchValue(url);
const success = yield saveToCache(value);
console.log('success:', success);
} catch(e) {
console.error(err);
}
}));
generator();
Each function will call the next one with the result of the method before.
var promises = [1,2,3].map((guid)=>{
return (param)=> {
console.log("param", param);
var id = guid;
return new Promise(resolve => {
// resolve in a random amount of time
setTimeout(function () {
resolve(id);
}, (Math.random() * 1.5 | 0) * 1000);
});
}
}).reduce(function (acc, curr, index) {
return acc.then(function (res) {
return curr(res[index-1]).then(function (result) {
console.log("result", result);
res.push(result);
return res;
});
});
}, Promise.resolve([]));
promises.then(console.log);

Categories