Async/Await result is empty after await execution - variables

I have a simple function:
var result = '';
var url = 'http://someurl.com/?action=perform-action';
(async function() {
let a = await fetch(url)
result = await a.text();
})()
console.log(result)
I'm trying to put the result into variable but it returns nothing.
My function simply checks if an email entered into an input exists in our database. Result is "Exists" or "OK". Works fine when I send it to the console but I need the result to perform other actions. If I save it to result it shows nothing.

Eventually your result variable will include the response from the fetch, but you're displaying the result before the fetch has completed its call.
Let's annotate the order:
var result = ''; // 1
var url = 'http://someurl.com/?action=perform-action'; // 2
(async function() {
let a = await fetch(url); // 5
result = await a.text(); // 6
})() // 3
console.log(result); // 4
If you moved your console.log call into the async function after the result is set you'd achieve your goal, like so:
var result = '';
var url = 'http://someurl.com/?action=perform-action';
(async function() {
let a = await fetch(url)
result = await a.text();
console.log(result);
})()
If the goal is to do something with that result outside the async call -- like somewhere else in your platform -- you'd need to observe the changes, or call an 'after result' function (which could be an injected callback.)
Here's a working example:
var result = '';
var url = 'https://jsonplaceholder.typicode.com/todos/1';
(async function() {
const a = await fetch(url);
result = await a.text();
console.log(result);
})()

Related

How to return blob item from localForage in service worker?

in my service worker i store mp4 video in indexedDB with localforage library in a blob data. It's work ! but i don't know how can i return this blob data.
This is my fetchHandler code :
const fetchHandler = async (event) => {
const getResponse = async () => {
const request = event.request;
if( request.destination === 'video' ){
// Get from indexedDB
const value = await localforage.getItem('video');
// How return the video from indexedDB cache ?
if( value ) return value; // not working
// Add in indexedDB
var networkResponse = await fetch(event.request);
localforage.setItem('video', networkResponse.blob() ).then(function (value) {
// Do other things once the value has been saved.
console.log(value);
}).catch(function(err) {
// This code runs if there were any errors
console.log(err);
});
}else{
const openedCache = await caches.open(SW_CACHE_NAME);
const cacheResponse = await openedCache.match(request);
if (cacheResponse) return cacheResponse;
var networkResponse = await fetch(event.request);
const cachePutResponse = await openedCache.put(request, networkResponse.clone());
if (cachePutResponse) return cachePutResponse;
}
return networkResponse;
};
event.respondWith(getResponse());
};
thanks for your help
You need to pass a valid Response object to event.respondWith(). That entails a response body (which is what you get back from localforeage.getItem()), but also some response headers.
You can use the Response constructor to create that, and return it from your getResponse() function.
The code could look something like:
const value = await localforage.getItem('video');
if (value) {
// See https://fetch.spec.whatwg.org/#bodyinit for what's accepted
// as a BodyInit.
return new Response(value, {
headers: {
// Replace this with the actual MIME type for the video.
'content-type': 'video/mp4',
// Include any other headers here if desired.
}
});
}

Use updated req variable in middleware after route execution

I have a middleware function I wrote to perform some logging for each HTTP request that comes in
export const winstonMiddlewareLogger = (req: express.Request, res: express.Response, next: express.NextFunction) => {
let _startTime = new Date();
res.on("finish", function() {
let responseTime = new Date().getTime() - _startTime.getTime() + "ms";
let method = req.method;
let url = req.originalUrl;
let body = req.body ? req.body : {};
let query = req.query;
let params = req.params;
let status = res.statusCode;
let msg = `HTTP ${req.method} ${req.url} ${responseTime}`;
let logDocument = {
msg,
method,
url,
params,
query,
body,
status,
responseTime,
};
logger.info(undefined, logDocument)
});
next();
};
Next thing I have a route
app.post("/slow", (req, res) => {
req.testParam = "test";
res.send("hello");
});
I want to be able to access the new property of the req parameter that is initiated in the /slow (testParam), in the res.on(...){...} event listener in my middleware function the next way:
if (req.hasOwnProperty('testParam')) {
console.log(req.testParam)
}
But the current state is that the req parameter is not updated no matter what I do in the route itself, because the req parameter it knows is only the one I get at the beginning of each request.
Changing the req variable in the route doesn't change it in the middleware which has already got a req variable of its own.
Any idea how to do it?
Ok so I found winston-express which actually does the things I wanted to.
What it does is to reassign the res.end function to a function he wrote himself.
This function can access the modified objects of req and res after the route has already executed.
So for the sake of showing how it works, I change my route to:
app.get("/", (req, res) => {
req._attributeFromRoute = "test";
res.send("hello");
});
And my middleware function looks something like this:
export const winstonMiddlewareLogger2 = (req: express.Request, res: express.Response, next: express.NextFunction) => {
let _startTime = new Date();
let end = res.end;
res.end = (chunk: any, encoding: string, cb?: () => void): void => {
res.end = end;
res.end(chunk, encoding, cb);
console.log(req._attributeFromRoute) // Notice that this property was not declared before the route execution, and now we can access it after it was defined
let responseTime = new Date().getTime() - _startTime.getTime() + "ms";
let method = req.method;
let url = req.originalUrl;
let body = req.body ? req.body : {};
let query = req.query;
let params = req.params;
let status = res.statusCode;
let msg = `HTTP ${req.method} ${req.url} ${responseTime}`;
let logDocument = {
msg,
method,
url,
params,
query,
body,
status,
responseTime,
};
logger.info(undefined, logDocument)
};
next();
};
And the way it will work is that the middleware function will wait for the route to execute and call the req.end function, which will enter the end function we created ourselfs.
We will then execute the original end function that had as a reference in the end variable.
Then we can do whatever we want with the updated objects of req and res.

await AsyncStorage return a promise instead value

I have an async function that calls AsyncStorage.getItem but always returns a promise.
I tried to use .then clause but the result is similar
I tried to use AsyncStorage.getItem out of the function but I get the error "await is a reserved word"
getDataStorage = async () => {
console.log("getDataStorage");
var data = '';
try {
data = await AsyncStorage.getItem('dataStorage');
console.log("getting data " + data);
return data;
} catch (error) {
console.log("----" + error.message);
}
};
componentDidMount(){
console.log("componentDidMount");
var data = this.getDataStorage();
console.log(data);
}
The result is first displays the promise then prints the value that I get with getItem().
I want to get the value, I suppose with await the function waits for the result of getItem, is it correct?
Yes, await functions wait for the result. But, in your case its only waiting till returning promise, so you have to change your code as:
componentDidMount = async () => {
console.log("componentDidMount");
data = await this.getDataStorage();
console.log(data);
}

Can't display from async function result

I need to display in my html variable: {my_dates}. The problem that I can't get it work with fetch but can do with old ajax request.
not working code:
created: function(){
//this.getTableData()
url = 'http://dlang.ru/test'
async function fetchAsync () {
const response = await fetch(url);
return await response.json();
}
this.my_dates = fetchAsync();
}
Working code:
$.ajax({
url: "http://dlang.ru/test",
success: function (data) {
Vue.set(app, "my_dates", data);
app.show = true;
}
});
If you want to be able to assign result of fetchAsync() to this.my_dates then entire created hook method needs to be declared as async.
Then you also need await in front of fetchAsync call:
created: async function () {
const url = 'http://dlang.ru/test';
async function fetchAsync() {
const response = await fetch(url);
return await response.json();
}
this.my_dates = await fetchAsync();
}
Please try this:
created: function(){
//this.getTableData()
url = 'http://dlang.ru/test'
async function fetchAsync () {
const response = await fetch(url);
const data = await response.json();
Vue.set(app, "my_dates", data);
app.show = true;
}
fetchAsync();
}

Nodejs: returning result on async result

I'm trying to code an RESTfull API in nodejs which is basically around a controller/modele schema and I meet some problems about the async nature of nodejs:
Station.js: (controller)
'use strict';
var url = require('url');
var Stations = require('./StationsService');
module.exports.stationsGet = function stationsGet(req, res, next){
var result = Stations.stationsGet(req.swagger.params['arg']);
if(typeof result !== 'undefined') {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(result || {}, null, 2));
}
else
res.end();
};
StationService.js: (modele)
'use strict';
exports.stationsGet = function(param){
var data_output = {};
var sql = 'SELECT * FROM foo WHERE args = ${foo}';
db.execute(sql, {foo: param}, db.queryResult.any, function(result){
// 'result' containing the query data
});
// Ideally: data_output = result;
return data_output;
}
The problem is if I use callback on my db.execute to continue, I have to give all the controller context (res, ...) to reply back to the client, and it break the modele/controller schema since my modele does the remaining controller work.
Is there a (easy?) way to get the result of the query in stationsGet() and then returning it?
Is it really against the nodejs nature and if so how to adopt the correct behavior in that case?
PS: I'm using swagger which has generated the files and base structure for nodejs.
You should use a callback in this case (take a look at promises as well)
your controller will look like this:
'use strict';
var url = require('url');
var Stations = require('./StationsService');
module.exports.stationsGet = function stationsGet(req, res, next){
Stations.stationsGet(req.swagger.params['arg'], function(err, result) {
if(typeof result !== 'undefined') {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(result || {}, null, 2));
}
else
res.end();
});
};
And the model you made must accept a callback as a last parameter, and you return err and the result like follows:
'use strict';
exports.stationsGet = function(param, cb){
var data_output = {};
var sql = 'SELECT * FROM foo WHERE args = ${foo}';
db.execute(sql, {foo: param}, db.queryResult.any, function(result){
cb(null, result); // first parameter is the error and the second is the result, this is pretty standard in node
});
}
I hope this helps you