Check image url using javascript async/await - javascript

I've seen multiple questions like this here but all of them just use alert or console.log as the result and I have a different problem.
I'm trying to verify if an image url is valid using async/await and axios.
async function checkImageUrl(imageUrl) {
let result = false;
const promise = await axios.get(imageUrl);
promise.then(() => {
console.log('result TRUE');
result = true;
}).catch(() => {
console.log('result false');
result = false;
});
console.log(result);
return result;
}
the image urls are in a json array. I use this in another function like this:
let imageValid = false;
someJson.some((obj) => {
if (obj?.image != null) {
imageValid = checkImageUrl(obj.image);
console.log(imageValid);
if (!imageValid) return true;
}
return false;
});
if (!imageValid) {
return;
}
I've used some console.logs to check the results. The problem is I never see those logs in async function and console.log(imageValid) always prints a Promise object in console. Is can't figure out how to implement this the right way.

You cant use async-await in some function. You can use tradition for-loop. Same time you can clean up the checkImageUrl function
function checkImageUrl(imageUrl) {
return axios
.get(imageUrl)
.then((x) => true)
.catch((x) => false);
}
async function main() {
let imageValid = false;
for (let index = 0; index < someJson.length; index++) {
const obj = someJson[index];
if (obj?.image != null) {
imageValid = await checkImageUrl(obj.image);
if (imageValid) {
break;
}
}
}
if (!imageValid) {
return;
}
}
main();

This is my solution:
async function checkImageUrl(imageUrl) {
let result = false;
try {
const res = await axios.get(imageUrl);
result = true;
} catch (err) {
console.log(err);
}
console.log("result", result);
return result;
}
(async () => {
let imageValid = false;
someJson.some((obj) => {
if (obj?.image != null) {
imageValid = await checkImageUrl(obj.image);
console.log(imageValid);
if (!imageValid) return true;
}
return false;
});
if (!imageValid) {
return;
}
})();

Related

Changing synchronous xmlhhtprequest to asynchronous promise gives different result

I was having trouble while converting a synchronous function to asynchronous.
the existing code is like below
$scope.getTask = function (input, id) {
var result = '';
if (condition) {
// Get all tasks.
var tasks = $scope.getAllTasks(id);
if (!angular.isUndefined(tasks)) {
var result = 'Failed';
for (var i = 0; i < tasks.length; i++) {
if (condition) {
result = 'Success';
break;
}
}
}
}
else if (condition) {
result = 'Failed';
}
else {
if (input != null || input != '') {
result = input.toLowerCase();
}
}
return result;
}
$scope.getAllTasks = function (id) {
var xhr = new XMLHttpRequest();
var url = "/api/workflow/" + id;
xhr.open("GET", url, false);
xhr.send();
return JSON.parse(xhr.responseText);
}
But now i need to make this async , so i have tried using promises but that didnt help.
It is not resolving properly. Please find what i have tried
$scope.getStatus = function (input, id) {
return new Promise((resolve, reject) => {
var result = '';
if(condition){
getAllTasks(id).then(function(response){
var tasks = response.data;
if (!angular.isUndefined(tasks)) {
var status = 'Failed';
for (var i = 0; i < tasks.length; i++) {
if (condition) {
result = 'Success';
break;
}
}
}
resolve(result);
return result;
});
resolve(result);
}
else if (condition) {
result = 'Failed';
}
else {
if (input != null || input != '') {
result = input.toLowerCase();
}
}
resolve(result);
return result;
});
}
var getAllTasks = function (id) {
const url = "/api/workflow/" + id;
return $http({method: 'GET', url})
.then((response) => {
return resolve(response)
});
}
But this is always returning [object promise].
I need to return the value as string like ' Failed' 'Success'.
Suggest what i am missing here.
I know promise will return a promise object from docs, but how to handle this.
$scope.getStatus is used in directives to fill the columns in jquesry datatable.
Code snippet is below
'sTitle': "<strong>" + $translate("list.StatusColumn") + "</strong>",
'mData': function (data, type, val) {
return $scope.getStatus(data.input, data.id);
},
'width': "16%",
'defaultContent': ""
Do this:
first,Dont handle your http request here if you are handling it in your other promise:
var getAllTasks = function (id) {
const url = "/api/workflow/" + id;
return $http({method: 'GET', url});
}
second: stop returning anything from this promise's callback function as you are returning result that you are also setting in resolve and you can get it in success handler of then function like this:
$scope.getStatus = function (input, id) {
var result = '';
if(condition){
getAllTasks(id).then(function(response){
var tasks = response.data;
if (!angular.isUndefined(tasks)) {
result = 'Failed';
for (var i = 0; i < tasks.length; i++) {
if (condition) {
result = 'Success';
break;
}
}
}
return result;
});
return result;
}
else if (condition) {
result = 'Failed';
}
else {
if (input != null || input != '') {
result = input.toLowerCase();
}
}
return result;
}
console.log($scope.getStatus());

How do you escape try/catch hell in Javascript?

Ok, I like(d) try/catch with await/async.
But what do I do with this.
I wanted to do this..
let a = await doAbc();
let b = await do123(a);
what it becomes instead is
let a, b;
try {
a = await doAbc();
} catch(e) {
a = await doZxc();
}
try {
b = await do123(a);
} catch (e) {
console.log(e);
return;
}
if (b.data == undefined) {
return -1;
} else {
return b;
}
At this point I'm regretting everything.
Remember that you can await any promise. So you could do:
let a = await doAbc().catch(doZxc); // or .catch(() => doZxc())
let b = await do123(a);
Or even
let b = await doAbc().catch(doZxc).then(do123);
Together with the rest of your code:
try {
let b = await doAbc().catch(doZxc).then(do123);
return b.data == undefined ? -1 : b;
} catch (e) {
console.log(e);
return;
}
If it's all in one logical function, you can group all your await in one try and then take action based on error.
let a
let b
try {
a = await doAbc();
b = await do123(a);
} catch (err) {
// take appropriate action based on err
}
Create to function first return a and second using first function returned value to create b , somthing like this code
function firstCode(){
try {
a = await doAbc();
} catch(e) {
a = await doZxc();
}
return a;
}
function secondFunction(){
try {
b = await do123(firstFunction());
} catch (e) {
console.log(e);
return;
}
}

Why is this async function failing to return any data?

So, a quick overview, this function is part of a larger app that ingests JSON data and prepares it to be rendered by Handlebars, which is then used for generating a PDF. This particular function has been giving me grief, as from my understanding of how async/await works, the data should be returned by the return returnArray at the bottom of the function. This however does not happen, and instead the empty array is returned. Could anyone offer insight as to why this is? (N.B. I've checked the data is present in iarr when it gets pushed, it's as though the return statement gets fired before the for loop has started.)
async function getPackageItem(item) {
try {
let returnArray = []
if (fs.existsSync(__dirname + "/../json/" + item.sku + ".json")) {
var file = fs.readFileSync(__dirname + "/../json/" + item.sku + ".json")
} else {
var file = fs.readFileSync(__dirname + "/../json/box.json")
}
const tb = JSON.parse(file);
for (var a = 0; a < item.quantity; a++) {
let iarr = [];
if (tb) {
tb.forEach(function(entry) {
ShopifyAuth.get('/admin/products/' + entry.product_id + '.json', (err, productData) => {
if (!err) {
ShopifyAuth.get('/admin/products/' + entry.product_id + '/metafields.json', (err, metafieldData) => {
if (!err) {
var itemObject = {};
var metaCounter = 0;
metafieldData.metafields.forEach(function(metadata) {
switch(metadata.key) {
case "notes": {
itemObject.wm_notes = metadata.value;
metaCounter++
break;
}
case "title": {
itemObject.title = metadata.value;
metaCounter++
break;
}
case "vintage": {
itemObject.year = metadata.value;
metaCounter++;
break;
}
case "shelfid": {
itemObject.shelf_id = metadata.value;
metaCounter++;
break;
}
case "bottleprice": {
itemObject.bottle_price = metadata.value;
metaCounter++;
break;
}
default: {
metaCounter++;
break;
}
}
if(metaCounter === metafieldData.metafields.length) {
itemObject.vendor = productData.product.vendor;
if (itemObject.title == undefined) {
itemObject.title = productData.product.title
}
if (itemObject.wm_notes == undefined) {
itemObject.wm_notes = " "
}
if (itemObject.year == undefined) {
itemObject.year = "Unspecified"
}
if (itemObject.shelf_id == undefined) {
itemObject.shelf_id = "N/A"
}
if (productData.product.images[1] == undefined) {
if (productData.product.images[0]) {
itemObject.logo = productData.product.images[0].src;
} else {
itemObject.logo = '';
};
} else {
itemObject.logo = productData.product.images[1].src;
}
itemObject.quantity = item.quantity;
iarr.push(itemObject)
if(iarr.length == tb.length) {
returnArray.push(iarr);
}
}
});
} else {
throw Error('Error retrieving product metadata');
}
})
} else {
throw Error('Error retrieving product data');
}
})
})
} else {
throw Error('Error loading JSON for specified box');
}
}
return returnArray;
} catch (e) {
console.log(e)
}
}
Edit: That's what I get for writing code at 3am, not sure how I missed that. Thanks for your feedback.
You marked your function async but you're not using await anywhere inside of it so you're not getting any of the benefits of using async. It doesn't make your function magically synchronous, you still have to manage asynchronicity carefully.
If ShopifyAuth.get supports returning a promise then await on the result instead of passing callbacks and your code will work, otherwise construct a Promise, do the async stuff in the promise, and return the promise from the function.
async function getPackageItem(item) {
let result = new Promise((resolve, reject) => {
// all your ShopifyAuth stuff here
if (err) {
reject(err);
}
resolve(returnArray);
});
return result;
}

Chaining Promises Cross Function Javascript

I suspect I've fundementally misunderstood Javascript promises, any ideas?
I have a pretty function that queries a database containing music that looks like this:
function searchDatabaseForTrack(query,loadedResults){
loadedResults = loadedResults || [];
desiredResults = 100;
if (loadedResults.length < desiredResults) {
try {
databaseApi.searchTracks(query, {"offset":loadedResults.length, "limit":"50", }).then(function(data){
i=0
if (data.tracks.items.length == 0) {
console.log(`Already loaded all ${loadedResults.length} tracks!`)
console.log(loadedResults)
return loadedResults;
}
else {
for (thing in data.tracks.items){
loadedResults.push(data.tracks.items[i]);
i=i+1;
}
console.log(loadedResults.length, " tracks collected");
searchDatabaseForTrack(query,loadedResults)
}
});
} catch(err) {
console.log("ERROR!", err)
console.log(loadedResults)
return loadedResults;
}
} else {
console.log(loadedResults)
return loadedResults;
}
}
And then a bit later, I try to call and use the data retrieved.
function getArtistTracks(artistName){
searchDatabaseForTrack(artistName).then(function(data){
console.log(songs);
songs.sort(function(a,b){
var c = new Date(a.track.album.release_date);
var d = new Date(b.track.album.release_date);
return d-c;
});
console.log("songs", songs);
var newsongs=[];
i=0
for (song in songs) {
newsongs.push(songs[i].track.uri);
i++
};
return newsongs;
});
}
What I'm trying to do is get the second function "getArtistTracks" to wait for the completion of the query in the first function. Now I could just call the databaseApi.searchTracks directly, but there's a limit of 50 tracks returned per result — which kind of screws me over.
searchDatabaseForTrack().then(...) shouldn't work since searchDatabaseForTrack() doesn't return a promise, so you can either return a promise or use an async function.
instead of a recursive function, you could simply call databaseApi in a for loop,
the desiredResult should be an argument and not hardcoded in the function,
async function searchDatabaseForTrack(query, desiredResults){
let loadedResults = [], data, currOffset = 0;
const iterations = Math.ceil(desiredResults / 50);
for(let n = 0 ; n < iterations; n++){
cuurOffset = n * 50;
data = await databaseApi.searchTracks(query, {"offset":currOffset, "limit":"50", });
if (data.tracks.items.length == 0) {
console.log(`Already loaded all ${loadedResults.length} tracks!`)
console.log(loadedResults)
return loadedResults;
}
else {
loadedResults = loadedResults.concat(data.tracks.items);
console.log(loadedResults.length, " tracks collected");
}
}
return loadedResults;
}
the rest should be fine as long as you add .catch() to handle errors ( as mentionned in previous answer ) which are thrown automatically without the need of the try/catch block :
function getArtistTracks(artistName, 100){
searchDatabaseForTrack(artistName).then((songs) => {
// your previous code
})
.catch((err) => {
// handle error
});
});
Have searchDatabaseForTrack use Promise.all to return the loadedResults after all results have been gotten. Also, make sure not to implicitly create global variables as you're doing with thing. For example, try something like this:
async function searchDatabaseForTrack(query) {
const desiredResults = 100;
const trackPromises = Array.from(
({ length: Math.ceil(desiredResults / 50) }),
(_, i) => {
const offset = i * 50;
return databaseApi.searchTracks(query, { offset, limit: 50 });
}
);
const itemChunks = await Promise.all(trackPromises);
const loadedResults = itemChunks.reduce((a, { tracks: { items }}) => (
[...a, ...items]
), []);
return loadedResults;
};
and
searchDatabaseForTrack(artistName).then((loadedResults) => {
// do stuff with loadedResults
})
.catch((err) => {
console.log("ERROR!", err)
// handle error
});

Node js return function does not return data

Hi so i just made this function and I'm trying to make return the data but for some reason it does not return the data but the function is called as i tried console logging it when the function is executed it works fine but it just does return the data when i want to use the function
As you can see I'm using the function trying to put the returned data in a array
Thank you all.
a.push(methods.UserInfo(id));
Here's all the code I'm using
methods.UserDatas = ((client, json)=> {
let a = [];
if (json.Params.length > 0) {
json.Params.forEach((id)=>{
if (id) {
a.push(methods.UserInfo(id));
}
});
let cmd = {
'Cmd': 'GetUserInfo',
'userinfo': a
};
packet.send(client, JSON.stringify(cmd));
}
});
methods.UserInfo = ((id)=> {
sql.query('SELECT * FROM users WHERE ?',[{id:id}], (err, row)=>{
if (err) {
throw err;
} else {
if (row.length > 0) {
let playerData = {};
playerData.userid = row[0].id;
playerData.strGender = row[0].Gender;
playerData.Username = row[0].Username;
let items = {};
sql.query('SELECT * FROM users_items WHERE ? AND equipped=1',[{userid:id}],(err,rows) => {
if (err) {
throw err;
} else {
if (rows.length > 0) {
for (var i =0; i< rows.length; i++) {
let item = DBData.items.get(parseInt(rows[i].itemid));
items[rows[i].equipment] = {
'ItemID': item.id,
'File':item.File,
};
}
}
playerData["equipment"] = items;
return playerData;
}
});
}
}
});
});
An async function (like for example
sql.query('SQL', [{PARAM:VALUE}], (ERR, RESULT) => { CODE }
) does not return as a regular function: you could use promises, for example (see here).
And note, too, that a sync function calling an async function, does not synchronously return values coming from that async function...

Categories

Resources