javascript - 仅在ajax请求成功后才迭代foreach循环数组

标签 javascript jquery ajax loops foreach

我想在 ajax 请求成功后下次进行迭代。

您可以在开发控制台上清楚地看到发生了什么。 foreach 循环内有一个 console.log(...); 函数。并且这个条件应该始终为真。我可以在这两个 AJAX 请求中使用 async: false 来实现此结果,但是它会阻塞 UI。

在我的特殊情况下,它不是一个普通的网页,只是一个项目,我可以这样做,但是,我不想使用它。我需要其他想法。

Console.log(....); 函数在不同时间返回不同的值,但左侧和右侧应该始终是相同的值。

例如:ESL_SC2 == habathcx - 错误,ESL_SC2 == ESL_SC2 - 正确。


打开控制台查看结果。只看JS部分。

$(function() {
  $("html").removeClass("no-js");
  $("#tabs").tabs();
  var xhr = new window.XMLHttpRequest(),
    users = [
      "ESL_SC2",
      "OgamingSC2",
      "cretetion",
      "freecodecamp",
      "storbeck",
      "habathcx",
      "RobotCaleb",
      "noobs2ninjas",
      "mhayia"
    ],
    index,
    ajaxDone,
    userResults = [],
    $search = $("#search"),
    keyCode,
    request;

  var getUserResults = function(callback) {
    index = 0;
    users.forEach(function(e) {
      $.ajax({
        url: "https://wind-bow.glitch.me/twitch-api/users/" + e,
        beforeSend: function() {
          ajaxDone = false;
        },
        success: function(d) {

          if (d.display_name !== undefined) {
            userResults[index] = {
              name: d.display_name
            };
            console.log(users[index] + " == " + e);
          }

          index++;

          if (index == users.length) {
            callback();
          }

          ajaxDone = true;
        },
        error: function() {
          alert(
            "AJAX Request failed. Please try again or contact using email <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="89e7bae6e5fce2e8fac9eee4e8e0e5a7eae6e4" rel="noreferrer noopener nofollow">[email protected]</a>."
          );
        },
        datatype: "json",
        cache: false
      });
    });
  };

  getUserResults(function() {
    index = 0;
    users.forEach(function(e) {
      $.ajax({
        url: "https://wind-bow.glitch.me/twitch-api/streams/" + e,
        success: function(d) {
          if (d.stream !== null) {
            userResults[index].status = d.stream.channel !== undefined ? 'Online' : '';
            userResults[index].title = d.stream.channel !== undefined ? d.stream.channel.status != undefined ? d.stream.channel.status : '' : '';
            userResults[index].url = d.stream.channel !== undefined ? d.stream.channel.url !== undefined ? d.stream.channel.url : '' : '';
          }

          if (userResults[index].name) {
            $('#tabs-1 table').append('<tr><td>' + userResults[index].name + '</td><td>' + (userResults[index].status ?
              'Online' : 'Offline') + '</td><td>' + (userResults[index].title ?
              userResults[index].title : '') + '</td></tr>');
          }

          index++;

          $("body").addClass("loaded");
        },
        error: function() {
          alert(
            "AJAX Request failed. Please try again or contact using email <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="82ecb1edeef7e9e3f1c2e5efe3ebeeace1edef" rel="noreferrer noopener nofollow">[email protected]</a>."
          );
        },
        datatype: "json",
        cache: false
      });
    });
  });
});
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  background-image: url("https://images8.alphacoders.com/702/702959.jpg");
  background-attachment: fixed;
  background-size: cover;
}

* {
  box-sizing: border-box;
}

.text-center {
  text-align: center;
}

.input {
  overflow: hidden;
  white-space: nowrap;
}

#tabs ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

#tabs a {
  background-color: #f44336;
  width: 33.33%;
  width: calc(100% / 3);
  padding: 10px 0;
  float: left;
}

#search {
  width: 100%;
  height: 3.125rem;
  border: none;
  font-size: 13px;
  color: #4f5b66;
  padding: 0 .9375rem;
}

.three-dots {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

table {
  width: 100%;
  border-spacing: 0;
  border-collapse: collapse;
  table-layout: fixed;
}

table tr {
  background-color: #f44336;
  color: #fff;
}

tr:first-child {
  background-color: #673ab7;
}

table td {
  padding: 0.625rem 0;
}

:focus {
  outline: 0;
}

.ui-state-active a {
  background-color: #2196f3 !important;
}

footer {
  font-size: 0.85rem;
  margin: 1rem 0;
}

a {
  text-decoration: none;
  color: #fff;
  position: relative;
}

footer a:before {
  content: "";
  position: absolute;
  width: 100%;
  height: 0.0625rem;
  bottom: 0;
  left: 0;
  background-color: #fff;
  visibility: hidden;
  -webkit-transform: scaleX(0);
  transform: scaleX(0);
  -webkit-transition: all 0.3s ease-in-out 0s;
  transition: all 0.3s ease-in-out 0s;
}

footer a:hover:before {
  visibility: visible;
  -webkit-transform: scaleX(1);
  transform: scaleX(1);
}

.search-results {
  background: #fff;
  margin: 1.5625rem 0;
  border-left: 0.3125rem solid #0ebeff;
  opacity: 0;
  display: none;
}

.search-results h4,
.search-results p {
  margin: 0;
  padding: 0.625rem;
  text-align: left;
}

.search-results a {
  color: #0ebeff;
  display: inline-block;
  margin: 1rem 0;
}

.search-results a:before {
  background-color: #0ebeff;
}

.wikisearch-container {
  width: 65%;
  margin: 2.5rem auto 0;
}


/* Screen loader */

#loader-wrapper {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000;
}

#loader {
  display: block;
  position: relative;
  left: 50%;
  top: 50%;
  width: 9.375rem;
  height: 9.375rem;
  margin: -4.6875rem 0 0 -4.6875rem;
  border-radius: 50%;
  border: 0.1875rem solid transparent;
  border-top-color: #fff;
  -webkit-animation: spin 1.75s linear infinite;
  /* Chrome, Opera 15+ Safari 5+ */
  animation: spin 1.75s linear infinite;
  /* Chrome, Firefox  16+, IE 10+, Opera */
  z-index: 1001;
}

#loader:before {
  content: "";
  position: absolute;
  top: 0.3125rem;
  left: 0.3125rem;
  right: 0.3125rem;
  bottom: 0.3125rem;
  border-radius: 50%;
  border: 0.1875rem solid transparent;
  border-top-color: #f7d130;
  -webkit-animation: spin 1.5s linear infinite;
  /* Chrome, Opera 15+ Safari 5+ */
  animation: spin 1.5s linear infinite;
  /* Chrome, Firefox  16+, IE 10+, Opera */
}

#loader:after {
  content: "";
  position: absolute;
  top: 0.9375rem;
  left: 0.9375rem;
  right: 0.9375rem;
  bottom: 0.9375rem;
  border-radius: 50%;
  border: 0.1875rem solid transparent;
  border-top-color: #0fff;
  -webkit-animation: spin 1.25s linear infinite;
  /* Chrome, Opera 15+ Safari 5+ */
  animation: spin 1.25s linear infinite;
  /* Chrome, Firefox  16+, IE 10+, Opera */
}

@-webkit-keyframes spin {
  0% {
    -webkit-transform: rotate(0deg);
    /* Chrome, Opera 15+, Safari 3.1+ */
    -ms-transform: rotate(0deg);
    /* IE 9 */
    transform: rotate(0deg);
    /* Firefox 16+, IE 10+, Opera */
  }
  100% {
    -webkit-transform: rotate(360deg);
    /* Chrome, Opera 15+, Safari 3.1+ */
    -ms-transform: rotate(360deg);
    /* IE 9 */
    transform: rotate(360deg);
    /* Firefox 16+, IE 10+, Opera */
  }
}

@keyframes spin {
  0% {
    -webkit-transform: rotate(0deg);
    /* Chrome, Opera 15+, Safari 3.1+ */
    -ms-transform: rotate(0deg);
    /* IE 9 */
    transform: rotate(0deg);
    /* Firefox 16+, IE 10+, Opera */
  }
  100% {
    -webkit-transform: rotate(360deg);
    /* Chrome, Opera 15+, Safari 3.1+ */
    -ms-transform: rotate(360deg);
    /* IE 9 */
    transform: rotate(360deg);
    /* Firefox 16+, IE 10+, Opera */
  }
}

.loaded #loader-wrapper,
.loader-section {
  position: fixed;
  top: 0;
  width: 50%;
  height: 100%;
  background: #000428;
  z-index: 1000;
}

#loader-wrapper .loader-section.section-left {
  left: 0;
}

#loader-wrapper .loader-section.section-right {
  right: 0;
}

.loaded #loader-wrapper .loader-section.section-left {
  -webkit-transform: translateX(-100%);
  /* Chrome, Opera 15+, Sadari 3.1+ */
  -ms-transform: transalteX(-100%);
  /* IE 9 */
  transform: translateX(-100%);
  /* Firefox 16+ IE 10+, Opera */
  -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  /* Android 2.1+ Chrome 1-25, iOS 3.2-6.1, Safari 3.2-6 */
  transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  /* Chrome 26, Firefox 16+, iOS 7+, IE 10+, Opera, Safari 6.1+ */
}

.loaded #loader-wrapper .loader-section.section-right {
  -webkit-transform: translateX(100%);
  /* Chrome, Opera 15+, Sadari 3.1+ */
  -ms-transform: transalteX(100%);
  /* IE 9 */
  transform: translateX(100%);
  /* Firefox 16+ IE 10+, Opera */
  -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  /* Android 2.1+ Chrome 1-25, iOS 3.2-6.1, Safari 3.2-6 */
  transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  /* Chrome 26, Firefox 16+, iOS 7+, IE 10+, Opera, Safari 6.1+ */
}

.loaded #loader {
  opacity: 0;
  position: fixed;
  -webkit-transition: all 0.3s ease-out;
  /* Android 2.1+ Chrome 1-25, iOS 3.2-6.1, Safari 3.2-6 */
  transition: all 0.3s ease-out;
  /* Chrome 26, Firefox 16+, iOS 7+, IE 10+, Opera, Safari 6.1+ */
}

.loaded #loader-wrapper {
  visibility: hidden;
  -webkit-transition: all 0.3s ease-out;
  /* Android 2.1+ Chrome 1-25, iOS 3.2-6.1, Safari 3.2-6 */
  transition: all 0.3s ease-out;
  /* Chrome 26, Firefox 16+, iOS 7+, IE 10+, Opera, Safari 6.1+ */
}

.no-js #loader-wrapper {
  display: none;
}


/* Loading animation */


/* Loading animation */

@keyframes lds-eclipse {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  50% {
    -webkit-transform: rotate(180deg);
    transform: rotate(180deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

@-webkit-keyframes lds-eclipse {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  50% {
    -webkit-transform: rotate(180deg);
    transform: rotate(180deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

.loading {
  position: relative;
  top: 0.59375rem;
  right: 0.9375rem;
  pointer-events: none;
  display: none;
}

.lds-eclipse {
  -webkit-animation: lds-eclipse 1s linear infinite;
  animation: lds-eclipse 1s linear infinite;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  margin-left: auto;
  box-shadow: 0.08rem 0 0 #0ebeff;
}

@media (max-width: 71.875em) {
  .wikisearch-container {
    width: 75%;
  }
}

@media (max-width: 50em) {
  .wikisearch-container {
    width: 85%;
  }
}

@media (max-width: 17.96875em) {
  .wikisearch-container {
    width: 100%;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="loader-wrapper">
  <div id="loader">
  </div>

  <div class="loader-section section-left"></div>
  <div class="loader-section section-right"></div>
</div>
<div class="twitchtv-container text-center">
  <div id="tabs">
    <ul>
      <li><a href="#tabs-1">All</a></li>
      <li><a href="#tabs-2">Online</a></li>
      <li><a href="#tabs-3">Offline</a></li>
    </ul>
    <input type="text" id="search" placeholder="Search...">
    <div id="tabs-1">
      <table>
        <tr>
          <td>User</td>
          <td>Status</td>
          <td>Title</td>
        </tr>
      </table>
    </div>
    <div id="tabs-2">
      <table>
        <tr>
          <td>User</td>
          <td>Status</td>
          <td>Title</td>
        </tr>
      </table>
    </div>
    <div id="tabs-3">
      <table>
        <tr>
          <td>User</td>
          <td>Status</td>
        </tr>
      </table>
    </div>
  </div>
  <footer>
    <a href="https://codepen.io/Kestis500">Created by LukasLSC</a>
  </footer>
</div>

最佳答案

虽然有“异步迭代”的技术,但连续获取一个用户是发出多个单独请求的一种缓慢方法。对于这种情况,并行获取要快得多。这就是您当前正在做的事情,但正如您所意识到的挑战是按照与请求相同的顺序获取响应。这是一个 Promise 可以很好解决的问题(使用 Promise.all 和 fetch)。由于您已经在使用 jQuery,因此您还可以使用 jQuery 的 Deferred objects 来完成它。和 $.when() :

var users = [
  "ESL_SC2",
  "OgamingSC2",
  "cretetion",
  "freecodecamp",
  "storbeck",
  "habathcx",
  "RobotCaleb",
  "noobs2ninjas",
  "mhayia"
];

// Transform array of usernames into an array of jQuery deferreds for
// each request. Note that this is actually sending all the requests
// in parallel.
var requests = users.map(function(user) {
  // No need to handle success/failures here, we'll chain those handlers
  // onto the `$.when()` call below.
  return $.ajax({
    url: "https://wind-bow.glitch.me/twitch-api/users/" + user,
    datatype: "json",
    cache: false
  });
});

// Use jQuery.when() to wait for all requests to complete, and provide
// the responses in order (this is the purpose of $.when() or Promise.all()).
// Note that $.when() expects multiple arguments so we need accomodate that
// by spreading our array with Function.prototype.apply(). (This could be
// written more simply in ES2015 as $.when(...requests)).
$.when.apply(null, requests)
  // done() is called after all requests are complete. All responses are
  // passed as arguments in the order the requests were sent.
  .done(function() {
    // Loop through all arguments. Using a `for` loop because built-in
    // `arguments` object isn't a real array, so we can't use
    // arguments.forEach().
    for (var i=0; i<arguments.length; i++) {
      var response = arguments[i];
      // Response is an array, the first element is the user object we want.
      var user = response[0];
      console.log(users[i] + " == " + user.display_name);
    }
  })
  // If any request fails, it will be handled here.
  .fail(function() {
    alert('User request failed.');
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

为了举例,这里有两个使用 Chrome 开发工具记录的网络瀑布,模拟“快速 3G”速度。并行版本快了 5 倍。

并行获取用户在 1 秒内完成: Parallel Requests Waterfall

按顺序获取用户需要 5 秒的时间: Serial Requests Waterfall

关于javascript - 仅在ajax请求成功后才迭代foreach循环数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48602440/

相关文章:

javascript - 返回 Ajax - 错误 - Symfony2

javascript - rails : Remote form in popup window not calling controller action

JavaScript:读取文件后尝试返回字符串时未定义类型

javascript - 谷歌图表 : Creating summary charts after category filters have been applied (+ JSFiddle issue)

javascript - 确定谁点击了电子邮件中的链接

javascript - 折叠 Accordion 面板时如何展开 HTML 网页?

javascript - 强制数字输入有两位小数并且只有两位

javascript - 如何从外部链接导航到 bootstrap 4 的特定选项卡

JavaScript 问题

javascript - 我怎样才能停止 AJAX 调用保持 PHP session 事件