saving data from promise in a variable - javascript

this is a problem that is going around for DAYS in my team:
We can't figure out how to save the result of a promise (after .then) in a variable.
Code will explain better what I mean:
We start with a simple async function that retrieves the first item of a list:
const helloWorld = () => [{ name: 'hi' }];
async function getFirstHelloWorld() {
const helloWorldList = await helloWorld();
return helloWorldList[0].name;
}
Now, we would like to call this function and save the content of aList:
let aList;
const a = async() => {
aList = await getFirstHelloWorld()
}
a().then(() => {
console.log('got result:', aList)
console.log('aList is promise:', aList instanceof Promise)
});
console.log(aList)
aList called within the .then(), console.logs the right value.
aList called outside the .then(), console.logs Promise { }
How can we save returned values from promises to a variable?

You cannot take an asynchronously retrieved value, stuff it in a higher scoped variable and then try to use it synchronously. The value will not be present yet because the asynchronous result has not been retrieved yet. You're attempting to use the value in the variable before it has been set.
Please remember that await only suspends execution of a local function, it does not stop the caller from running. At the point you do an await, that function is suspended and the async function immediately returns a promise. So, NO amount of await or return gets you anything by a promise out of an async function. The actual value is NEVER returned directly. All async functions return a promise. The caller of that function then must use await or .then() on that promise to get the value.
Try running this code and pay detailed attention to the order of the log statements.
console.log("1");
const helloWorld = () => [{ name: 'hi' }];
async function getFirstHelloWorld() {
const helloWorldList = await helloWorld();
return helloWorldList[0].name;
}
let aList;
const a = async() => {
console.log("beginning of a()");
aList = await getFirstHelloWorld()
console.log("end of a()");
}
console.log("2");
a().then(() => {
console.log('got result:', aList)
console.log('aList is promise:', aList instanceof Promise)
});
console.log("3");
console.log('attempting to use aList value');
console.log(aList)
console.log("4");
That will give you this output:
1
2
beginning of a()
3
attempting to use aList value
undefined
4
end of a()
got result: hi
aList is promise: false
Here you will notice that you are attempting to use the value of aList BEFORE a() has finished running and set the value. You simply can't do that in Javascript asynchronous code, whether you use await or .then().
And, remember that the return value from an async function becomes the resolved value of the promise that all async functions return. The value is not returned directly - even though the code syntax looks that way - that's a unique property of the way async functions work.
Instead, you MUST use the asynchronous value inside the .then() where you know the value is available or immediately after the await where you know the value is available. If you want to return it back to a caller, then you can return it from an async function, but the caller will have to use .then() or await to get the value out of the promise returned from the async function.
Assigning an asynchronously retrieved value to a higher scoped variable is nearly always a programming error in Javascript because nobody wanting to use that higher scoped variable will have any idea when the value is actually valid. Only code within the promise chain knows when the value is actually there.
Here are some other references on the topic:
Why do I need to await an async function when it is not supposedly returning a Promise?
Will async/await block a thread node.js
How to wait for a JavaScript Promise to resolve before resuming function?
Using resolved promise data synchronously
How to Write Your Code
So, hopefully it is clear that you cannot escape an asynchronous result. It can only be used in asynchronous-aware code. You cannot turn an asynchronously retrieved result into something you can use synchronously and you usually should NOT be stuffing an asynchronous result into a higher scoped variable because that will tempt people writing code in this module to attempt to use the variable BEFORE is is available. So, as such, you have to use the value inside a .then() handler who's resolved value has the value you want or after an await in the same function where the await is. No amount of nesting in more async functions let you escape this!
I've heard some people refer to this as asynchronous poison. Any asynchronous operation/value anywhere in a flow of code makes the entire thing asynchronous.
Here's a simplified version of your code that shows returning the value from an async function which will make it the resolved value of the promise the async function returns and then shows using .then() on that promise to get access to the actual value. It also shows using .catch() to catch any errors (which you shouldn't forget).
FYI, since this is not real asynchronous code (it's just synchronous stuff you've wrapped in some promises), it's hard to tell what the real end code should be. We would need to see where the actual asynchronous operation is rather than just this test code.
const helloWorld = () => [{ name: 'hi' }];
async function getFirstHelloWorld() {
const helloWorldList = await helloWorld();
return helloWorldList[0].name;
}
getFirstHelloWorld().then(name => {
// use the name value here
console.log(name);
}).catch(err => {
console.log(err);
});

You need to return the variable like this and use it within the .then callback.
const a = async() => {
const res = await getFirstHelloWorld()
return res
}
a().then((data) => {
console.log('got result:', data)
});

Related

What is the point of the await keyword within an async function in terms of returning a value?

I've researched many many posts and articles, and documentation. I'm seeking deeper understanding.
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
The await expression causes async function execution to pause until a Promise is settled, [...]
let fetchLocation = () => {
//fetches information from satellite system and
//returns a Vector2 of lat long on earth
return new Promise(resolve => {
setTimeout(() => {
resolve({
lat: 73,
long: -24
});
}, 2000);
});
}
//async functions automatically return a promise.
let main = async() => {
//awaits the promises resolution
let result = await fetchLocation();
console.log("I'm the awaited promise result", result)
//immediately returns a promise as promise pending
return result;
}
console.log(main().then(res => console.log("I'm the original promise, just passed along by the async function, it didn 't a-wait for me", res)))
Before going down this rabbit hole, I knew async/await was syntactical sugar to make async code look synchronous.
I therefore fully expected to see main return the lat long coordinates. Instead it returns a promise.
A couple questions.
Is the MDN documentation wrong? Does it not actually pause execution? It seems that the await keyword does not actually "pause" function execution... invoking main immediately returns a Promise<pending> object. However, after it returns we receive the value of the fulfilled promise in the awaited variable result. I suppose this came from the event loop? (And an async return statement is still synchronous.)
So it seems that await unwraps a promise, and async wraps a promise, but you need to use await within async. I get that await might actually be promise.then() underneath the hood but if they want to make it fully synchronous in appearance, why not have the async function return the resolved promise value when used with await? Otherwise async await seems a bit redundant.
Is the MDN documentation wrong?
No
Does it not actually pause execution?
It pauses the execution of the async function, hands a Promise back to the calling function — because it hasn't reached the point in the async function where it knows what to return — then the execution of the calling function (and the rest of the code) continues.
However, after it returns we receive the value of the fulfilled promise in the awaited variable result. I suppose this came from the event loop?
When the event loop stops being busy (running the code that called the async function in the first place and anything else that it picks up in the meantime) and the promise that was being awaited resolves, then the async function is woken up and given the resolved value of the function to continue processing.
why not have the async function return the resolved promise value when used with await?
Because that would block the entire event loop, which is why asynchronous logic (starting with callback style APIs) was introduced into JS in the first place.
Otherwise async await seems a bit redundant.
Consider a situation where you want to request a number of URLs from an API serially (so that you don't shove too many simultaneous requests at the API):
const data = [];
for (let i = 0; i < urls.length; i++) {
const response = await fetch(urls[i]);
const response_data = await response.json();
data.push(response_data);
}
If you were to rewrite that without await then you'd probably end up with something recursive to count your way through the loop. It would be significantly more complex.
async/await makes dealing with complex combinations of promises simple, and simple promises trivial.
knew async/await was syntactical sugar to make async code look synchronous.
And it does that inside the async function and only inside it.
It doesn't really pause the function, it just allows you to write the rest of the function code as if it were. But it's really just wrapping the rest of the code of the function into a .then().
E.g.
await foo = someFunc();
console.log(foo);
is executed like
someFunc().then((foo => {
console.log(foo);
});
Since it's really still asynchronous, you can't return the resolved value, because the original calling function returns immediately. But if the calling function is also declared async, it returns a Promise, and the caller can either use await again (so it appears to be synchronous) or use .then().

Javascript Await/Async Feature - What if you do not have the await word in the function?

I am learning about Javascript ES2017 async/await feature.
Been reading a lot about it, and came across an understanding that await is like yield, and allows us to wait for the promises to complete.
From https://javascript.info/async-await
async function showAvatar() {
// read our JSON
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
// read github user
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
let githubUser = await githubResponse.json();
// show the avatar
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// wait 3 seconds
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
showAvatar();
The question I have is, can I add await to every single line of code?
Or what happens if I remove the word await?
And another question is, if async/ await makes the code seems to run synchronously and in order, why don't we don't use it at all (means make everything stay synchronous in the first place?)
Thank you!
async functions are just syntactic sugar around Promises. It does nothing to change the function to be synchronous. In fact any function that is async implicitly returns a Promise object.
All await does is provide a convenient way to wait for a Promise. If you remove the await keyword, then the Promise will not be "unwrapped," which is not what you want if your function is going to operate on the result of that Promise.
To illustrate, this is the desugared version of your async function:
function showAvatar() {
let githubUser;
// read our JSON
return fetch('/article/promise-chaining/user.json').then(response => {
return response.json();
}).then(user => {
// read github user
return fetch(`https://api.github.com/users/${user.name}`);
}).then(githubResponse => {
return githubResponse.json();
}).then(user => {
githubUser = user;
// show the avatar
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// wait 3 seconds
return new Promise((resolve, reject) => setTimeout(resolve, 3000));
}).then(() => {
img.remove();
return githubUser;
});
}
So await essentially just adds a .then callback to a Promise. Without await being specified, you'll just have a Promise object, not the result of the Promise.
await tells the runtime to wait for the promise returned from the expression on the right-hand side to be fulfilled.
In the following code control is stopped in the async function until the promise returned by the fetch invocation is fulfilled, and the response value sent to the fulfilled promise is printed to the console.
async function go() {
let response = await fetch('http://www.example.com');
console.log(response); // print the response after some time
}
go();
If the await keyword was omitted then control would immediately continue to the next line of the function and the the promise returned by fetch would be immediately printed to the console.
async function go() {
let response = fetch('http://www.example.com');
console.log(response); // print the promise from fetch immediately
}
go();
await is a contextual keyword that only means something special when used inside a function marked async. By marking a function async you are telling the runtime to:
treat the function as a generator function
yield a value where the user types await (usually a promise)
wrap the function in special handling logic so that progress through the function only occurs when each promise yielded by await is fulfilled
In this way, asynchronous control flows can be written in a style closer to the traditional synchronous style. ie. without nesting, callbacks or visible promises. try..catch can also be used in the normal way.
As another answer mentions, async, and await are syntactic sugar that ask the runtime to use existing objects (generator functions and Promises) behind the scenes to make async code easier to read and write.
can you await every line
I would guess you can. If the expression on the right of the await results in a promise, then the async/await behaviour detailed above occurs.
If the expression on the right of the await does not result in a promise, then I would guess the value is wrapped in a resolved promise for you, and logic continues per the above, as though the value came from an immediately resolved promise. This is a guess.
First, async / await, work with promises. If you are not calling from an async function or the await sentence is not then compatible, it won't work. In most cases if you remove await, you are going to end with a Promise and not the value of the promise.
Secondly, there are some cases that you may want to continue with the execution of the code while you are resolving some asynchronous task.

Async function not returning value, but console.log() does: how to do? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I have an es6 class, with an init() method responsible for fetching data, transforming it, then update the class's property this.data with newly transformed data.
So far so good.
The class itself has another getPostById() method, to just do what it sounds like. Here is the code for the class:
class Posts {
constructor(url) {
this.ready = false
this.data = {}
this.url = url
}
async init() {
try {
let res = await fetch( this.url )
if (res.ok) {
let data = await res.json()
// Do bunch of transformation stuff here
this.data = data
this.ready = true
return data
}
}
catch (e) {
console.log(e)
}
}
getPostById(id){
return this.data.find( p => p.id === id )
}
}
Straightforward, except I have an async/await mechanism in the init() method.
Now, this code will work correctly:
let allPosts = new Posts('https://jsonplaceholder.typicode.com/posts')
allPosts.init()
.then( d => console.log(allPosts.getPostById(4)) )
// resulting Object correctly logged in console
but it only gets printed into the console:
How could I use allPosts.getPostById(4) as a return of a function ?
Like:
let myFunc = async () => {
const postId = 4
await allPosts.init() // I need to wait for this to finish before returning
// This is logging correct value
console.log( 'logging: ' + JSON.stringify(allPosts.getPostById( postId ), null, 4) )
// How can I return the RESULT of allPosts.getPostById( postId ) ???
return allPosts.getPostById( postId )
}
myFunc() returns a Promise but not the final value. I have read several related posts on the subject but they all give example of logging, never returning.
Here is a fiddle that includes two ways of handling init(): using Promise and using async/await. No matter what I try, I can't manage to USE the FINAL VALUE of getPostById(id).
The question of this post is: how can I create a function that will RETURN the VALUE of getPostById(id) ?
EDIT:
A lot of good answers trying to explain what Promises are in regards to the main execution loop.
After a lot of videos and other good reads, here is what I understand now:
my function init() correctly returns. However, within the main event loop: it returns a Promise, then it is my job to catch the result of this Promise from within a kinda parallel loop (not a new real thread). In order to catch the result from the parallel loop there are two ways:
use .then( value => doSomethingWithMy(value) )
use let value = await myAsyncFn(). Now here is the foolish hiccup:
await can only be used within an async function :p
thus itself returning a Promise, usable with await which should be embed in an async function, which will be usable with await etc...
This means we cannot really WAIT for a Promise: instead we should catch parallel loop indefinitely: using .then() or async/await.
Thanks for the help !
As for your comment; I'll add it as answer.
The code you write in JavaScript is run on one thread, that means that if your code could actually wait for something it will block any of your other code from getting executed. The event loop of JavaScript is explained very well in this video and if you like to read in this page.
A good example of blocking code in the browser is alert("cannot do anything until you click ok");. Alert blocks everything, the user can't even scroll or click on anything in the page and your code also blocks from executing.
Promise.resolve(22)
.then(x=>alert("blocking")||"Hello World")
.then(
x=>console.log(
"does not resolve untill you click ok on the alert:",
x
)
);
Run that in a console and you see what I mean by blocking.
This creates a problem when you want to do something that takes time. In other frameworks you'd use a thread or processes but there is no such thing in JavaScript (technically there is with web worker and fork in node but that's another story and usually far more complicated than using async api's).
So when you want to make a http request you can use fetch but fetch takes some time to finish and your function should not block (has to return something as fast as possible). This is why fetch returns a promise.
Note that fetch is implemented by browser/node and does run in another thread, only code you write runs in one thread so starting a lot of promises that only run code you write will not speed up anything but calling native async api's in parallel will.
Before promises async code used callbacks or would return an observable object (like XmlHttpRequest) but let's cover promises since you can convert the more traditional code to a promise anyway.
A promise is an object that has a then function (and a bunch of stuff that is sugar for then but does the same), this function takes 2 parameters.
Resolve handler: A function that will be called by the promise when the promise resolves (has no errors and is finished). The function will be passed one argument with the resolve value (for http requests this usually is the response).
Reject handler: A function that will be called by the promise when the promise rejects (has an error). This function will be passed one argument, this is usually the error or reason for rejection (can be a string, number or anything).
Converting callback to promise.
The traditional api's (especially nodejs api's) use callbacks:
traditionalApi(
arg
,function callback(err,value){
err ? handleFail(err) : processValue(value);
}
);
This makes it difficult for the programmer to catch errors or handle the return value in a linear way (from top to bottom). It gets even more impossible to try and do things parallel or throttled parallel with error handling (impossible to read).
You can convert traditional api's to promises with new Promise
const apiAsPromise = arg =>
new Promise(
(resolve,reject)=>
traditionalApi(
arg,
(err,val) => (err) ? reject(err) : resolve(val)
)
)
async await
This is what's called syntax sugar for promises. It makes promise consuming functions look more traditional and easier to read. That is if you like to write traditional code, I would argue that composing small functions is much easier to read. For example, can you guess what this does?:
const handleSearch = search =>
compose([
showLoading,
makeSearchRequest,
processRespose,
hideLoading
])(search)
.then(
undefined,//don't care about the resolve
compose([
showError,
hideLoading
])
);
Anayway; enough ranting. The important part is to understand that async await doesn't actually start another thread, async functions always return a promise and await doesn't actually block or wait. It's syntax sugar for someFn().then(result=>...,error=>...) and looks like:
async someMethod = () =>
//syntax sugar for:
//return someFn().then(result=>...,error=>...)
try{
const result = await someFn();
...
}catch(error){
...
}
}
The examples allways show try catch but you don't need to do that, for example:
var alwaysReject = async () => { throw "Always returns rejected promise"; };
alwaysReject()
.then(
x=>console.log("never happens, doesn't resolve")
,err=>console.warn("got rejected:",err)
);
Any error thrown or await returning a rejected promise will cause the async function to return a rejected promise (unless you try and catch it). Many times it is desirable to just let it fail and have the caller handle errors.
Catching errors could be needed when you want the promise to succeed with a special value for rejected promises so you can handle it later but the promise does not technically reject so will always resolve.
An example is Promise.all, this takes an array of promises and returns a new promise that resolves to an array of resolved values or reject when any one of them rejects. You may just want to get the results of all promises back and filter out the rejected ones:
const Fail = function(details){this.details=details;},
isFail = item => (item && item.constructor)===Fail;
Promise.all(
urls.map(//map array of urls to array of promises that don't reject
url =>
fetch(url)
.then(
undefined,//do not handle resolve yet
//when you handle the reject this ".then" will return
// a promise that RESOLVES to the value returned below (new Fail([url,err]))
err=>new Fail([url,err])
)
)
)
.then(
responses => {
console.log("failed requests:");
console.log(
responses.filter(//only Fail type
isFail
)
);
console.log("resolved requests:");
console.log(
responses.filter(//anything not Fail type
response=>!isFail(response)
)
);
}
);
Your question and the comments suggest you could use a little intuition nudge about the way the event loop works. It really is confusing at first, but after a while it becomes second nature.
Rather than thinking about the FINAL VALUE, think about the fact that you have a single thread and you can't stop it — so you want the FUTURE VALUE -- the value on the next or some future event loop. Everything you write that is not asynchronous is going to happen almost immediately — functions return with some value or undefined immediately. There's nothing you can do about. When you need something asynchronously, you need to setup a system that is ready to deal with the async values when they return sometime in the future. This is what events, callbacks, promises (and async/await) all try to help with. If some data is asynchronous, you simply can not use it in the same event loop.
So what do you do?
If you want a pattern where you create an instance, call init() and then some function that further process it, you simply need to setup a system that does the processing when the data arrives. There are a lot of ways to do this. Here's one way that's a variation on your class:
function someAsync() {
console.log("someAsync called")
return new Promise(resolve => {
setTimeout(() => resolve(Math.random()), 1000)
})
}
class Posts {
constructor(url) {
this.ready = false
this.data = "uninitilized"
this.url = url
}
init() {
this.data = someAsync()
}
time100() {
// it's important to return the promise here
return this.data.then(d => d * 100)
}
}
let p = new Posts()
p.init()
processData(p)
// called twice to illustrate point
processData(p)
async function processData(posts) {
let p = await posts.time100()
console.log("randomin * 100:", p)
}
init() saves the promise returned from someAsync(). someAsync() could be anything that returns a promise. It saves the promise in an instance property. Now you can call then() or use async/await to get the value. It will either immediately return the value if the promise has already resolved or it will deal with it when it has resolved. I called processData(p) twice just to illustrate that it doesn't calle the someAsync() twice.
That's just one pattern. There are a lot more — using events, observables, just using then() directly, or even callbacks which are unfashionable, but still can be useful.
NOTE: Wherever you use await it has to be inside an async function.
Check out the UPDATED FIDDLE
You need to use await myFunc() to get the value you expect from getPostById because an async function always returns a promise.
This sometimes is very frustrating as the whole chain needs to be converted into async functions but that's the price you pay for converting it to a synchronous code, I guess. I am not sure if that can be avoided but am interested in hearing from people who have more experience on this.
Try out the below code in your console by copying over the functions and then accessing final and await final.
NOTE:
An async function CAN contain an await expression.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
There is no rule that is must have await in order to even declare an async function.
The example below uses an async function without await just to show that an async function always returns a promise.
const sample = async () => {
return 100;
}
// sample() WILL RETURN A PROMISE AND NOT 100
// await sample() WILL RETURN 100
const init = async (num) => {
return new Promise((resolve, reject) => {
resolve(num);
});
}
const myFunc = async (num) => {
const k = await init(num);
return k;
}
// const final = myFunc();
// final; This returns a promise
// await final; This returns the number you provided to myFunc

What is the correct syntax for a method declared as async?

I stumbled upon the following ES6 method during a rewiew:
async getUsers(res) {
User.findAll().then(users => res.json(users));
}
This seems buggy to me. I would have expected the following:
async getUsers(res) {
return User.findAll().then(users => res.json(users));
}
But then, I know that async has many tricks such as auto-wrapping promises, so is my intuition correct?
The code as it is written (without the return) is likely fine as long as the caller does not need access to the asynchronously retrieved value.
First off, async is needed as part of your function definition ONLY if you plan on using await inside the function. If you aren't using await inside (which your code does not show), then the async part of the definition is not needed. So, it could probably be just this:
getUsers(res) {
User.findAll().then(users => res.json(users));
}
Second, if a caller wants to use await on the getUsers() function, then it needs to return a promise (as you proposed). If the caller will not use await with it or otherwise need any access to a return value, then the return is not necessary. So, if you wanted to use await on this function, then it should probably be this:
getUsers(res) {
// return promise so caller can get async value
return User.findAll().then(users => {
res.json(users);
return users; // return value so caller can get access to the value
});
}
So, the original code may be just fine as long as the caller is never expecting an asynchronous return value from that function (which is possible here because the result of the async operation is being sent with res.json() and that may be the only result that is needed. As far as await/async are concerned, you only have to return a promise from functions that you plan to use await on.
To recap:
async is only needed if you plan on using await inside the function. Your function probably doesn't even need the async keyword on it at all.
A returned promise is only needed if the caller wants to be able to get access to the asynchronous response either via a traditional f().then() or via let x = await f().
A caller can await a function that is not marked as async. The await will get the return value from the function and, if the return value is not a promise it will wrap it in a resolved promise. If it is a promise, it will wait for it to resolve.
FYI, this is a very good, short and sweet review of async/await and how they interact with promises.

When using the await?

I'm using sequelize with typescript. I know that the code is asynchronous, and
Here, I am using promise, and the code works..
I would want to know when I must to use await keyword ?
const promises = []
let tabIdDoc = requestedListIdDoc.toString().split(",")
for (let thisIdDoc of tabIdDoc) {
promises.push(sequelize.models['Document'].findById(thisIdDoc))
}
q.all(promises).then((resultReq) => {
const lstDocs = []
for (let MyDoc of resultReq) {
if (MyDoc.matriculeDoc != "") {
lstDocs.push(sequelize.models['FolderDocContent'].findOrCreate({
where: {
}
}))
}
}
q.all(lstDocs).then(() => {
return response.status(201)
})
}
Is await keyword necessary here ?
You don't ever have to use await as other programming using .then() can always get the job done, but there are numerous times when using await makes your code simpler. This is particularly true when you are trying to sequence a number of asynchronous operations and even more so when you need to use previous results in more than one operation that follows.
Example #1: Serializing operations in a for loop
Suppose you want to save a bunch of items to your database, but for various reasons, you need to save them one by one and you need to save them in order (in other words, you need to sequence them):
async function saveItems(shoppingList) {
for (let item of shoppingList) {
// for loop will pause until this promise resolves
await db.save(item);
}
}
saveItems(myList).then(() => {
// all done
}).catch(err => {
// error here
});
Without using await, you'd have to use a significantly more verbose design pattern using .reduce() or perhaps a recursive function that you call on the completion of the prior operation. This is a lot simpler way to sequence iteration of a loop.
Example #2: Sequencing different operations in a function
Suppose, you need to contact three different outside services. You need to get some data from one, then use that data when you make a second API call, then use both of those pieces of data in a third API call:
const rp = require('request-promise');
async function getPrice(productName) {
// look up productID
const productID = await rp(`http://service1.com/api/getID?name=${productName}`);
// use productID to lookup price
const productPrice = await rp(`http://service1.com/api/getPrice?id=${productID}`);
// put both productID and price into the shopping cart
return rp({uri: 'http://service1.com/api/addToCart', body: {name: productName, id: productID}, json: true);
}
getPrice("Nikon_d750").then(total => {
// all done here, total is new cart total
}).catch(err => {
// error here
});
Both of these examples would require more code in order to properly sequence the asynchronous operations and you'd have to nest logic following inside a .then() handler. Using await instructs the JS interpreter to do that nesting for you automatically.
Some other examples here on MDN.
Several rules to keep in mind with await:
You can only use it inside a function prefixed with the async keyword as in my examples above.
All async functions return a promise. If you have an explicit return value in the function as in return x, then that value becomes the resolved value of the promise when all the asynchronous operations are done. Otherwise, it just returns a promise that has an undefined resolved value. So, to use a result from an async function or to know when it's done, you either have to await the result of that function (inside another async function) or you have to use .then() on it.
await only suspends execution within the containing function. It is as if the rest of the code in the function is placed inside an invisible .then() handler and the function will still return its promise immediately when it hits the first await. It does not block the event loop or block other execution outside the async function. This confuses many people when they first encounter await.
If the promise that you await rejects, then it throws an exception within your function. That exception can be caught with try/catch. If it is not caught, then the async function automatically catches it and rejects the promise that the function returns where the thrown value is the reject reason. It is easy when first using await to completely forget about the error cases when promises you are awaiting can reject.
You never necessarily must use await. You however should use await in every place where you'd otherwise have then with a callback, to simplify your code.
In your example:
const promises = requestedListIdDoc.toString().split(",").map(thisIdDoc =>
sequelize.models['Document'].findById(thisIdDoc)
);
const resultReq = await q.all(promises);
const lstDocs = resultReq.filter(myDoc => MyDoc.matriculeDoc != "").map(myDoc =>
sequelize.models['FolderDocContent'].findOrCreate({
where: {}
})
);
await q.all(lstDocs);
return response.status(201)

Categories

Resources