简体   繁体   中英

What is wrong with this Promise.all solution

I need to loop through an array of items and check if each item's type matches desired type. Once all the checking are done, add the ones that meet requirement to a dropdown select box. In an array where 2 items meet the requirement, this code checks is only adding the first item to the dropdown always, what is wrong with it?

var promises = [];
var html = "";

for (var i = 0; i < items.length; i++) {
  var promise = new Promise(function(resolve, reject){
    $.ajax({
      url: "url" + items[i], 
      dataType: "json",
      success: function (data) {
        console.log(data); 
        console.log(data.type); // "mytype"
        console.log(typeof data.type); // string
        if(data.type == "mytype") {
          html += "<option value='" + data.id + "'>" + items[i] + "</option>";
          resolve();
        }
      }
    });
  promises.push(promise); 
  });
}

console.log(promises) // (2) [undefined, Promise]

Promise.all(promises).then(() => {
  $("#dropdownBox").html(html);
});

EDIT: someone pointed out that I need to use each instead of forloop to make a closure, I tried it but still does not work. I tried doing

$.each(items, function(index){...}

and

items.forEach(function(index){...}

and modified what's inside the loop accordingly but no luck. This post ( JavaScript closure inside loops – simple practical example ) does not help me.

One of the issues you have is not resolving the promise if the type doesn't meet condition.

Your for() loop also doesn't create a closure so i won't be what you expect it to be when request completes

Since $.ajax returns a promise here's a less anti-pattern approach using map() to create closure and the promise array

// map array of promises
var promises = items.map((item) => {
  // return $.ajax promise
  return $.ajax({
    url: "url" + item,
    dataType: "json"
  }).then((data) => {
    let html = '';
    if (data.type == "mytype") {
      html += "<option value='" + data.id + "'>" + item + "</option>";
    }
    return html;
  });
});

Promise.all(promises).then((res) => {
  // res is array of  html (or empty) strings returned in each then() above
  $("#dropdownBox").html(res.join(''));
}).catch(err => console.log('At least one request failed'));

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM