简体   繁体   English

与 then 的链接功能无法正常工作

[英]Chaining function with then doesn't work correctly

Hey I got a problem which my functions which are chained with .then doesn't work correctly, not in the order they should.嘿,我遇到了一个问题,我用 .then 链接的函数不能正常工作,而不是按照它们应该的顺序工作。

my code:我的代码:

 <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>

output:输出:

users variable on the myFun function should have all the data from the first restCall and push the data from the second restCall to the same variable. myFun 函数上的 users 变量应该包含第一个 restCall 中的所有数据,并将第二个 restCall 中的数据推送到同一个变量。 The variables does get the data, but the myFun function runs before them so the users variable inside it is null.变量确实获取了数据,但 myFun 函数在它们之前运行,因此其中的 users 变量为空。

result pic:结果图: 在此处输入图片说明

how can I fix that?我该如何解决?

.then accepts a function as a parameter, but in .then接受一个函数作为参数,但在

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

you're invoking myFun immediately, and passing its return value to the second .then .您立即调用myFun ,并将其返回值传递给第二个.then It evaluates to:它评估为:

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

The myFun runs immediately , while the interpreter attempts to put together the Promise chain (before the response has come back). myFun立即运行,而解释器尝试将 Promise 链放在一起(在响应返回之前)。

Pass a function that invoked myFun instead:传递一个调用myFun的函数:

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

You may also use .bind , which will create a function with the desired parameters, but won't call it:您也可以使用.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>

Only invoke a function inside a .then 's parameter list if the function returns a function, eg:如果函数返回一个函数,则仅调用.then的参数列表中的函数,例如:

const fnThatReturnsFn = arg => resolveValue => console.log(arg, resolveValue);
someProm()
  .then(fnThatReturnsFn('somearg'));

$.ajax returns a promise-like object. $.ajax返回一个类似promise 的对象。 so use that to your advantage, by returning the data from your ajax calls in a then within your functions.因此,通过在函数中的then返回来自 ajax 调用的数据,可以充分利用它。

Note that I've used one of @CertainPerformance's suggestions in their answer to fix the myFun issue.请注意,我在他们的回答中使用了@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>

Note that I'm using an object to collect both users and user into a single object;请注意,我使用一个对象将usersuser收集到一个对象中; you could just as easily use an array.您可以轻松地使用数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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