的链接功能将无法正常工作

时间:2019-03-05 22:18:42

标签: javascript ajax rest promise

嘿,我遇到了一个问题,我的函数链接到.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>

输出:

myFun函数上的

users变量应具有来自第一个restCall的所有数据,并将来自第二个restCall的数据推送到同一变量。 变量确实获取了数据,但是myFun函数在它们之前运行,因此其中的用户变量为null。

结果图片: enter image description here

我该如何解决?

2 个答案:

答案 0 :(得分:1)

.then接受 function 作为参数,但在

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

您立即调用 myFun,并将其返回值传递给第二个.then。评估结果为:

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

myFun立即运行 ,而解释器尝试将Promise链放在一起(在响应返回之前)。

通过调用 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'));

答案 1 :(得分:0)

$.ajax返回类似promise的对象。因此可以通过在函数内的then中从ajax调用中返回数据来利用这一点。

请注意,我已使用@CertainPerformance's suggestions in their answer中的一个来解决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>

请注意,我正在使用一个对象将usersuser收集到一个对象中;您可以轻松地使用数组。