Javascript promise not waiting to resolve before then [duplicate] - javascript

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 2 years ago.
I'm writing javascript code to parse a huge file (several GBs) and I'm using FileReader's readAsArrayBuffer function with promises (see below):
function readRaw(fc, length) {
const fileReader = new FileReader();
return new Promise((resolve, reject) => {
fileReader.onloadend = function(value) {
console.log("onloadend");
fc.offset += length;
resolve(new Uint8Array(value.result));
}
fileReader.onerror = (err) => {
console.error(err);
reject(err);
}
const slice = fc.handle.slice(fc.offset, fc.offset + length);
fileReader.readAsArrayBuffer(slice);
});
}
function parsefile(file) {
let fc = { handle: file, offset: 0 };
let buffer = {};
var promise = readRaw(fc, 32);
promise.then(function(value) {
console.log("success: offset=" + fc.offset)
buffer = value
}).catch((e) => {
console.error(e);
});
console.log("offset=" + fc.offset);
}
document
.getElementById('fileToRead')
.addEventListener('change', function () {
let file = this.files[0];
if (file) {
parsefile(file);
}
}, false);
My expectation is that Promise.prototype.then() should wait for the promise to resolve before continuing but I'm not able to get it to work no matter how I tweak the code or switch to use async/await.
Expected:
onloadend
success: offset=32
offset=32
Actual
offset=0
onloadend
success: offset=32
Thanks in advance for any help and enlightenment!

Per Why await beats Promise.then(...)"
The fundamental difference between await and vanilla promises is that await X() suspends execution of the current function, while promise.then(X) continues execution of the current function after adding the X call to the callback chain.

Related

How to get around async promise executor [duplicate]

This question already has answers here:
Is it an anti-pattern to use async/await inside of a new Promise() constructor?
(5 answers)
What is the explicit promise construction antipattern and how do I avoid it?
(3 answers)
Closed 5 months ago.
I'm fetching images from my app through js but eslint is warning about using async promise executors. I know that in other cases like this, you could just remove the promise all-together, but not sure if that's applicable here.
Here is the code in question:
async fn() {
let urls = _.map($('#img-container img'), (img) => $(img).attr('src'));
urls = await Promise.all(urls.map((url) => new Promise(async (res) => { // FIXME - async promise executor
const blob = await (await fetch(url)).blob();
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = res;
})));
urls = urls.map((u) => u.target.result);
return Buffer.from(pako.deflate(JSON.stringify(urls))).toString('base64');
}
How could I restructure this to get rid of this pattern? Or should I just dismiss the warning?
ESlint is complaining because there shouldn't be a need for an explicit Promise's executor to be async, because it generally means you're doing something wrong (mixing things that are already promisesque with building explicit promises).
You'll have a better time altogether (and ESlint won't complain either) if you refactor things so the callback-style FileReader API is wrapped in its own function that returns a promise (and that executor doesn't need to be async).
function blobToDataURL(blob) {
return new Promise((res) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = res;
});
}
async function x() {
let urls = _.map($("#img-container img"), (img) => $(img).attr("src"));
const dataUrls = await Promise.all(
urls.map(async (url) => {
const blob = await fetch(url).blob();
return blobToDataURL(blob);
}),
);
}

Why returns the map function an array of promises instead of just img object? (Jonas Schmedtmann) [duplicate]

This question already has answers here:
Use async await with Array.map
(9 answers)
Best way to call an asynchronous function within map?
(14 answers)
Closed 1 year ago.
I'm learning from Jonas Schmedtmann JS course. At the end of the async function section, I just don't understand some things.
Here are the three function:
const createImage = function (imgPath) {
return new Promise(function (resolve, reject) {
const img = document.createElement('img');
img.src = imgPath;
img.addEventListener('load', function () {
imgContainer.append(img);
resolve(img);
});
img.addEventListener('error', function () {
reject(new Error('Image not found'));
});
});
};
const loadNPause = async function () {
try {
// Load image 1
let img = await createImage('img/img-1.jpg');
console.log(img);
console.log('Image 1 loaded');
await wait(2);
img.style.display = 'none';
// Load image 1
img = await createImage('img/img-2.jpg');
console.log('Image 2 loaded');
await wait(2);
img.style.display = 'none';
} catch (err) {
console.error(err);
}
};
const loadAll = async function (imgArr) {
try {
const imgs = imgArr.map(async img => await createImage(img));
console.log(imgs);
const imgsEl = await Promise.all(imgs);
console.log(imgsEl);
imgsEl.forEach(img => img.classList.add('parallel'));
} catch (err) {
console.error(err);
}
};
loadAll(['img/img-1.jpg', 'img/img-2.jpg', 'img/img-3.jpg']);
By the loadAll function, when I log the imgs variable, it gives me an array of promises. Jonas said that is because of async function, it returns always a promise.
But, if I delete the async await keywords, like this "const imgs = imgArr.map(img => createImage(img));", it returns also a promise.
However, in the loadNPause function when I log the img variable, it is not a promise, but an img object.
Can you tell me why is that? In both function is returned a promise from the createImage function, in loadNPause gives me back an img Object, but in loadAll function when go through the array, then the createImage returns a promises.

Async/Await - code executes before promise is resolved [duplicate]

This question already has answers here:
How do I convert an existing callback API to promises?
(24 answers)
Closed 2 years ago.
I have an async function that processes an Array and call another async function by increasing time interval by each element.
I wait for all promises to resolve and then I save the resulting Array in a file. Though for some reasons the write file operation executes before the Promises are resolved.
Can somebody tell me what I might be doing wrong?
The read and write file functions are turned into promise with node util and the getGuidesList returns a promise.
(async () => {
try {
const file = await readFilePromise('./kommuner.json');
const municipalities = JSON.parse(file).municipalities;
console.log(municipalities);
const municipalities_new = await Promise.all(municipalities.map(async (municipality, index) => {
setTimeout(async () => {
let guides = await getGuidesList(municipality.municipality_id);
// const guides = [];
if (typeof guides === 'string') {
guides = [];
}
console.log(`Number of guides for ${municipality.municipality_name}: ${guides.length}`);
Reflect.set(municipality, 'guides_number', guides.length);
Reflect.set(municipality, 'guides', guides);
console.log(municipality)
}, index * 5000);
}))
console.log(municipalities_new);
await writeFilePromise('./kommuner_guide.json', JSON.stringify({
"municipalities": municipalities_new
}));
} catch (err) {
console.log(err);
}
})();
The problem here is this line:
setTimeout(async () => {
you do a setTimeout call. That will schedule the callback to be called later. But you don't wait for that callback to happen. Instead use some promisified version of setTimeout:
const timer = ms => new Promise(res => setTimeout(res, ms));
then you can
await timer(2000);
await /*other stuff*/;

function not returning value from amazon-s3 file but prints when i console [duplicate]

This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 3 years ago.
The below code not returning amazon s3 content, it works when console the data value.
I have tried declare variable outside function and tried to return from function still, not works
const getMeridianToken1 = () =>{
s3 = new aws.S3();
// Create the parameters for calling listObjects
var bucketParams = {
Bucket: 'bucket-name',
Key: 'access_token.json'
};
// Call S3 to obtain a list of the objects in the bucket
s3.getObject(bucketParams, function(err, data) {
if (!err) {
var result = JSON.parse(data.Body.toString());
console.log("working here---",result.access_token);
return result.access_token; //this is not returning
}
});
//return JSON.parse(data.Body.toString()); //if hard code here it works, if i return s3 conteent the data variable not available here
}
console.log("not working",getMeridianToken1);
The issue is the s3 method being asynchronous. See this
function getMeridianToken1() {
const s3 = new aws.S3();
// Create the parameters for calling listObjects
var bucketParams = {
Bucket: 'bucket-name',
Key: 'access_token.json'
};
return new Promise((resolve, reject) => {
s3.getObject(bucketParams, function(err, data) {
if (!err) {
var result = JSON.parse(data.Body.toString());
resolve(result.access_token);
}
reject(err);
});
});
}
getMeridianToken1()
.then(val => console.log(val));
Hope this helps
s3.getObject is a asychronous call the control reaches on return JSON.parse() line early which is why data variable is not available outside the callback function.
Solution is to wrap s3.getObject in promise or use async/await.

getting async nodejs value from each callback calls [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
var async = require('async');
var square = function (id, callback) {
Business.prototype.getBusinessUser(id,function(userObject){
return callback(userObject);
});
};
async.eachSeries(findBusinessResult, function (businessObject, callback) {
//console.log("results from square");
var result = square(businessObject["id"] , function(result){
console.log(result);
});
callback(); // Alternatively: callback(new Error());
}, function (err,results) {
if (err) { throw err; }
console.log('Well done :-)!');
console.log(results);
});
Why does the result always become undefined: any help please.
async is reserved word in ES7 and might give you problem later, when it's implemented.
What you might want to consider is actually using async/await togheter with babel.
Some browser is starting to implement it already
var square = id =>
new Promise(rs =>
Business.prototype.getBusinessUser(id, rs)
)
async search() {
for (let businessObject of findBusinessResult) {
let result = await square(businessObject.id)
console.log(result)
}
}
I hope this will be a game changer solution for most ppl. This is making ASYC java callback into somthing which look like sync with effiecent callback handling. Its my three days of challange. [Callbacks][1] are indeed a a major challage in javacript and here is how to solve issue using promises .
install bluebird
npm install bluebird --save
//inyour code
var Promise = require('bluebird'); //yeah awsome bird indeed :)
function extendBusinessObjectPromise(id,element) {
return new Promise(function(resolve, reject) {
Business.prototype.getBusinessUser( id ,function(userObject){
var extend = require('util')._extend;
mergedJson = userObject;
elements = element;
extend({},elements);
extend(elements,mergedJson);
global.businesssWithUsers.push(elements); //sahred object
resolve(global.businesssWithUsers)
})
})
}
//NOW how do you i call the promise result inside a foreach loop and get its value returned as callback result. seem crazy idea :(
Person.prototype.getPersons = function(filter , callback) {
//this my own Bill count since i have one using one user account
global.businesssWithUsers = [];
models.PersonModel.findAll(filter_combined).then(function (findBusinessResult) {
global.businesssWithUsers = []
var extend = require('util')._extend;
var mergedJsonArray = [];
if (findBusinessResult==null) {
return callback(false,"no result found");
}
var promiseBusinessResult = null; //promise reslover :)
var findBusinessResult =JSON.parse(JSON.stringify(findBusinessResult));
findBusinessResult.forEach(function(eachElement) {
var id = element["userId"];
promiseBusinessResult = extendBusinessObjectPromise(id,element);
});
promiseBusinessResult.done(function(result){
callback(true,result); //pass the result to main function
});
}).catch(function (err) {
log.error(err["errors"][0]["message"])
callback(false,err["errors"][0]["message"])
return
})
}
Success at last. Cheers!

Categories

Resources