【问题标题】:When do functions actually get called? How do I control it? [duplicate]函数何时真正被调用?我该如何控制它? [复制]
【发布时间】:2018-02-22 22:31:52
【问题描述】:

这里是JS新手,尝试通过jQuery的$.get()创建一些对API的简单调用并处理接收到的数据。

问题是 - 显然 - 这个函数被调用......好吧,无论何时。但不是在我期望它被调用的时候(即它在代码中的位置)。我会很好的

  1. get(...) 内做所有事情,只要我可以使用父作用域中的循环、计数器等(就像我习惯的那样)
  2. 首先从get() 调用中获取接收到的数据,然后再对其进行处理

但这似乎都不可能。

我想这就是人们在谈论 AJAX 中的异步 JavaScript 时的意思。很好很好,但是我该如何解决我的问题呢?

$(document).ready(function() {
  for (var i = 0; i < 5; i++) {
    console.log(i);
    $.get("test.php", function(data) {
      console.log(i);
    });
    console.log(i);
  }
});
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

给予

00 11 22 33 44 44444

但我希望它是

000 111 222 333 444

我希望这是有道理的。

额外问题:我最好使用 PHP 来获取here 所述的数据,然后将其转换为 JS,如here 所述并按计划继续?

编辑/解决方案:

我的额外问题最终导致我提出了这样的问题(简化):

<script>
<?php
$data = array();

for ($row = 0; $row < 5; $row++) {
    $response = json_decode(file_get_contents("test.php?access_token=".$row));
    array_push($data,$response);
}

$js_data = json_encode($data);
echo "var data_all = ". $js_data .";\n";
?>

$(document).ready(function(){
    //do JS stuff with the data_all array
});
</script>

这样做的好处是不会将访问令牌放在所有人的视线范围内。

如果我的方法有问题,我很乐意在 cmets 中阅读相关内容,否则我会在找到可行的解决方案时考虑完成此问题。感谢您指出这个问题的副本,这是一个有趣的阅读。

【问题讨论】:

  • 主要问题:在一个循环中触发多个 ajax,实际上是非顺序的(想想赛马)。哎呀,你甚至可能会在 '4' 之后发现一个 '0' ;) 额外问题:有点取决于你在做什么,你从哪里获得你需要的数据,以及你想要什么。
  • 回调被异步调用的事实并不是导致您的问题的原因,相反,导致您的问题的原因是它们直到循环完成后一段时间才被调用。跨度>

标签: javascript php jquery function asynchronous


【解决方案1】:

欢迎来到异步编程。

您将无法强制它让您按自己的意愿循环。你必须遵守 async 的规则,不能反过来强加。

从根本上讲,您必须习惯以异步方式运行异步代码。这就是为什么它有一个回调让你知道它已经完成了。

如果您想串行处理多个异步请求,您需要以某种方式将它们排队,然后在第一个完成时从队列中读取下一个。

// just a dummy async function that waits 100ms before finishing
const asyncFunction = (value) => new Promise(resolve => setTimeout(() => resolve(value), 100));

// data to call
const queue = ['A', 'B', 'C', 'D', 'E'];

const processQueue = (queue) => {
  if (queue.length == 0) {
    return Promise.resolve();
  } else {
    console.log('running', queue[0]);
    return asyncFunction(queue.shift())
      .then(val => {
        console.log(val);
        return processQueue(queue)
      });
  }
}

processQueue(queue)
  .then(() => console.log('all done'));

基本上,您有一些数据队列(在我的情况下是字母,但在您的情况下可能是 URL)。您取出第一个,然后将其关闭,等待它完成,然后运行队列中的下一个。然后你重复这个直到它们都完成。

上面的语法使用Promises(与$.get() 和朋友一起使用),这通常是更现代的方法,但回调版本(如您的示例)非常相似:

// just a dummy async function that waits 100ms before finishing
const asyncFunction = (value, callback) => setTimeout(() => callback(value), 100);

// data to call
const queue = ['A', 'B', 'C', 'D', 'E'];

const processQueue = (queue, callback) => {
  if (queue.length == 0) {
    callback();
  } else {
    console.log('running', queue[0]);
    asyncFunction(queue.shift(), val => {
      console.log(val);
      processQueue(queue, callback)
    });
  }
}

processQueue(queue, () => console.log('all done'));

【讨论】:

  • 1.不知道为什么这个答案被否决了。非常感谢,现在我至少可以确认我的问题是什么了。这对我来说并不明显。 2. 由于您的大部分语法对我来说都是新的(基本上是昨天开始使用 JS,jQuery 被宣传为“简单的 JS”,现在我在这里),在给出您的建议之前,我可能会尽量避免异步编程。尽管如此,我还是非常感谢代码 sn-ps。如果没有其他答案,将在一天左右接受。 (考虑到反对票和重复,这似乎很可能。)
猜你喜欢
  • 1970-01-01
  • 2016-01-09
  • 2019-01-15
  • 2015-08-10
  • 2011-02-16
  • 2011-09-19
  • 1970-01-01
  • 2019-11-18
  • 2015-05-12
相关资源
最近更新 更多