Robert Brush Robert Brush - 29 days ago 8
Javascript Question

promises and for loops

I have this code:

function ProductObj(product, i) {
var self = this;

self.photo = product.photos.medium_half;
self.title = product.name;
self.tagline = product.tagline;
self.url = product.url;

self.htmlView = "";
self.index = i;


//this async call is slow, very slow
self.updateHTML = function() {
return new Promise(resolve => {
$.get('product-template.html', function (template) {
self.htmlView = template.replace('{image}', self.photo)
.replace('{title}', self.title)
.replace('{tagline}', self.tagline)
.replace('{url}', self.url);

console.log('updateHTML ' + self.index + ' ran');
resolve();
});
});
};
}


when self.updateHTML is called, self.updateDOM is called at the same time

self.updateDOM = function() {
return new Promise(resolve => {
var thisHTML = '';

for( var i = 0; i < self.products.length; i++) {

if (i % 3 === 0 ) {
thisHTML += "<div class='row'>";
console.log('START')
}

thisHTML += self.products[i].htmlView;

if ((i % 3 === 2) || i === (self.products.length - 1) ) {
thisHTML += "</div>";
console.log('finish')
}

if(i === (self.products.length -1)) {
$("#content").append(thisHTML);
}
}
resolve();
})
}


naturally, I used promises to attempt to fix this as such

page.getProducts('data.json')
.then( page.updateProductHTML )
.then( page.updateDOM )
.then( someOtherFunction );


Page.getProducts
executes first and returns a promise to
page.updateProductHTML
. So far my promise in
page.updateProductHTML
is resolving before assignments can finish in
self.updateHTML
and
updateDOM
is firing but it needs values from updateHTML before it can finish

The problem arises from this
page.updateProductHTML
as it runs this code

self.updateProductHTML = function() {
return new Promise(resolve => {
for( var i = 0; i < self.products.length; i++){

self.products[i].updateHTML();

}
resolve();
})
};


I attempted to wrap the above code in a promise and resolve outside of the for loop but the
$.get()
call is still working

from what I understand I need to keep updateHTML in a promise but it doesn't seem to do anything different in its present state since I can't use a
.then
in my for loop in
page.updateProductHTML


How do I force
page.updateProductHTML
to not resolve until it finishes its calls in
self.updateHTML
?

small recap I want this order
self.getProducts() => self.updateProducts => sef.updateDOM => other functions

Answer

You should use Promise.all():

self.updateProductHTML = function() {
  return Promise.all(self.products.map(product => product.updateHTML()));
};
Comments