关于 javascript:promises 和 for 循环

promises and for loops

我有这个代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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();
            });
        });
    };
}

调用self.updateHTML时,同时调用self.updateDOM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 self.updateDOM = function() {
        return new Promise(resolve => {
            var thisHTML = '';

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

                if (i % 3 === 0 ) {
                    thisHTML +="";
                    console.log('START')
                }

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

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

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

当然,我使用 promise 来尝试解决这个问题

1
2
3
4
 page.getProducts('data.json')
        .then( page.updateProductHTML )
        .then( page.updateDOM )
        .then( someOtherFunction );

Page.getProducts 首先执行并向 page.updateProductHTML 返回一个Promise。到目前为止,我在 page.updateProductHTML 中的Promise是在 self.updateHTML 中完成分配之前解决,并且 updateDOM 正在触发,但它需要 updateHTML 中的值才能完成

问题来自这个 page.updateProductHTML,因为它运行这个代码

1
2
3
4
5
6
7
8
9
10
self.updateProductHTML = function() {
        return new Promise(resolve => {
            for( var i = 0; i < self.products.length; i++){

                self.products[i].updateHTML();

            }
            resolve();
        })
    };

我试图将上述代码package在一个Promise中并在 for 循环之外解析,但 $.get() 调用仍在工作

据我了解,我需要将 updateHTML 保持在一个Promise中,但它在当前状态下似乎没有做任何不同的事情,因为我不能在 page.updateProductHTML 的 for 循环中使用 .then pb>

我如何强制 page.updateProductHTML 在它完成对 self.updateHTML 的调用之前不解析?

小回顾我想要这个订单self.getProducts() => self.updateProducts => sef.updateDOM => other functions


你应该使用 Promise.all():

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

你可以使用promise.all,它会等到你的所有promise都被解决,然后执行依赖于早期方法的其他方法。

我的 Codepen 链接上有一个示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
self.updateProductHTML = function() {
  var updateMethods = [];
  for (var i = 0; i < self.products.length; i++) {
    updateMethods.push(self.products[i].updateHTML());
  }
  return Promise.all(updateMethods);
}

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

    if (i % 3 === 0) {
      thisHTML +="";
      console.log('START')
    }

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

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

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

updateProductHTML().then(updateDOM);