声明。我的一位朋友正在寻找高级JS程序员的工作。那不是一个真正的问题,但是因为我可以想象它在哪里以及如何成为现实,我决定在这里发布它。
问题(测试任务)。按照我的说法,我可以在这里引用它,如果你认为我弄错了。 如何编写一个函数,将异步请求发送到给定的URL数组,连接每个请求的结果并返回连接的字符串?哦,还有另一个限制:IE9 +,当前的FF,当前的Chrome 。朋友的答案(尽可能礼貌):不能做。
我的回答是一样的。由于浏览器JS中没有线程(它不是NodeJS)并且没有sleep
函数,因此您不能等到所有请求都被处理完毕。 Web workers?他们aren't supported in IE9。而且,他们无论如何都不会有所帮助。您可以使用sync
XMLHttpRequest.open
的{{1}}标记逐个发送请求,但是(这是我的建议)如果所有请求都被发送到同一服务器上,该服务器执行一些可以执行的数学运算仅限单个CPU内核,您的罚款为x4 / x8 / x16次。无论如何,它被测试任务禁止。当然,您可以在回调函数中连接结果,但也禁止它,因为您必须返回结果。
但我不是JS大师,所以我把问题转发给了我的另一位朋友(我是这么认为的)。他建议创建其他浏览器选项卡,每个URL一个,它将发送请求并将结果写入其标题中。主选项卡将循环通过选项卡,等待所有标题都不为空。由于选项卡是独立执行的,因此应该可以使用。然后他尝试了解决方案,并说它只在IE中工作(有一些副作用)。换句话说,没有解决方案。
但是雇主回复了我的第一个朋友的声明解决方案存在,但拒绝发送该函数的JS代码。
那么,问题是某种拖钓吗?或者有一个解决方案我可以使用,如果我遇到一种情况,我真的必须连接异步请求结果(我知道它在JS中是一个坏主意)。
答案 0 :(得分:3)
以下是对各种选项的讨论:
使用同步Ajax 并返回结果。同步ajax是一个可怕的想法,挑战说使用异步请求,所以大概这是一个禁止,但我在这里包括它,因为它确实让你直接返回结果。
如果在同一窗口中使用async ajax,则根本无法直接返回结果。结果完成后,您可以调用回调,或者返回承诺,然后在结果可用时调用.then()
处理程序回调。您无法旋转并等待异步ajax完成,因为在您返回并让事件队列进入下一个事件之前,Ajax并发症无法返回给您。
如果您将Ajax放入webWorker (同步或异步),您可以根据需要对webWorker进行编码,但它可以与主线程进行通信的唯一方法是通过一条消息,主线程无法接收该消息,直到您从原始函数返回到事件队列中的下一条消息。同样,您无法旋转并等待来自webWorker的消息,因为在当前执行线程完成之后它才会回复给您。因此,您必须先从您的函数返回,然后才能从webWorker获取结果。
您可以将Ajax放入iFrame或其他窗口,然后在完成后从其他窗口回传到当前窗口。这与以前的解决方案具有相同的问题,因为在当前函数完成并返回之后,您将无法从iFrame或其他窗口接收回传,以便事件可以从事件队列中处理。因此,您必须在从另一个窗口获取结果之前从函数返回。
您可以将Ajax放入iFrame或其他窗口,然后从主窗口轮询该窗口中的某个变量。这可能在某些浏览器中有效,但我无法建立一个成功的测试来证明它可以工作。
答案 1 :(得分:0)
function concatenatesResults(urls, cb) {
var temp = [], i = urls.length
urls.forEach(function (url, key) {
//its async so not block the foreach
$.ajax({
url: url,
success: function (data) {
temp[key] = data //be sure it is in a good order
i--
if (i === 0) cb(temp.join("")) //if this is teh last one return the data
}
})
})
}
concatenatesResults([/* URLS*/], function(data){console.log(data)})