Функция сцепления с тогда не работает правильно - PullRequest
0 голосов
/ 06 марта 2019

Эй, у меня проблема с тем, что мои функции, связанные с .then, работают неправильно, не в том порядке, в котором должны.

мой код:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>

    <script>
      var users = [];
      var user = null;

      function restCallA() {
        return $.ajax({
          url: "https://reqres.in/api/users?page=2",
          type: "GET",
          success: function(response) {
            users = response.data;
            console.log("users", users);
          }
        });
      }
      function restCallB() {
        return $.ajax({
          url: "https://reqres.in/api/users/2",
          type: "GET",
          success: function(response) {
            user = response.data;
            console.log("user", user);
          }
        });
      }
      function myFun(testArg) {
        users.push(user);
        console.log("why users is null?", testArg, users);
      }

      $(function() {
        restCallA()
          .then(restCallB)
          .then(myFun("test"));
      });
    </script>
  </body>
</html>

выход: * +1010 *

Пользовательская переменная в функции myFun должна иметь все данные из первого restCall и передавать данные из второго restCall в ту же переменную. Переменные получают данные, но функция myFun выполняется перед ними, поэтому переменная users внутри нее равна нулю.

Результат фото: enter image description here

как я могу это исправить?

Ответы [ 2 ]

1 голос
/ 06 марта 2019

.then принимает функцию в качестве параметра, но в

restCallA()
  .then(restCallB)
  .then(myFun("test"));

вы немедленно вызываете myFun и передаете возвращаемое значение второму .then. Оценивается:

restCallA()
  .then(restCallB)
  .then(undefined);

myFun немедленно запускает , в то время как интерпретатор пытается собрать цепочку обещаний (до того, как ответ вернется).

Передайте функцию, которая вызвала myFun вместо:

restCallA()
  .then(restCallB)
  .then(() => myFun("test"));

Вы также можете использовать .bind, который создаст функцию с нужными параметрами, но не вызовет ее:

restCallA()
  .then(restCallB)
  .then(myFun.bind(undefined, "test"));

var users = [];
var user = null;

function restCallA() {
  return $.ajax({
    url: "https://reqres.in/api/users?page=2",
    type: "GET",
    success: function(response) {
      users = response.data;
      console.log("users", users);
    }
  });
}

function restCallB() {
  return $.ajax({
    url: "https://reqres.in/api/users/2",
    type: "GET",
    success: function(response) {
      user = response.data;
      console.log("user", user);
    }
  });
}

function myFun(testArg) {
  users.push(user);
  console.log("why users is null?", testArg, users);
}

$(function() {
    restCallA()
      .then(restCallB)
      .then(() => myFun("test"));
});
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>

Вызывать функцию из списка параметров .then можно только в том случае, если функция возвращает функцию, например:

const fnThatReturnsFn = arg => resolveValue => console.log(arg, resolveValue);
someProm()
  .then(fnThatReturnsFn('somearg'));
0 голосов
/ 06 марта 2019

$.ajax возвращает объект, похожий на обещание.так что используйте это в своих интересах, возвращая данные из ваших вызовов ajax в then в ваших функциях.

Обратите внимание, что я использовал одно из предложений @ CertainPerformance в их ответе исправить проблему myFun.

<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Document</title>
</head>

<body>
  <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>

  <script>
    function restCallA() {
      return $.ajax({
        url: "https://reqres.in/api/users?page=2",
        type: "GET"
      }).then(response => response.data);
    }

    function restCallB(users) {
      return $.ajax({
        url: "https://reqres.in/api/users/2",
        type: "GET"
      }).then(response => {
        return {
// ES2015 method for adding a property named "users" with the value of the users variable
          users, 
          user: response.data
        };
      });
    }

    function myFun(testArg, usersAndUser) {
      usersAndUser.users.push(usersAndUser.user);
      console.log(testArg);
    }

    $(function() {
      restCallA()
        .then(restCallB)
        .then((usersAndUser) => myFun("test", usersAndUser));
    });
  </script>
</body>

</html>

Обратите внимание, что я использую объект, чтобы собрать как users, так и user в один объект;вы можете так же легко использовать массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...