Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript XMLHttpRequest和作用域的影响_Javascript_Php_Ajax - Fatal编程技术网

Javascript XMLHttpRequest和作用域的影响

Javascript XMLHttpRequest和作用域的影响,javascript,php,ajax,Javascript,Php,Ajax,赏金提示:简单的问题是,如果是异步请求,为什么我不需要担心goGet在请求完成之前被删除呢 我有一个用PHP生成的表单,它生成了许多HTML行,我将它们称为条目。每个条目有两个选项,删除和编辑,每个选项可能需要创建零个或多个XMLHttpRequests 为了使处理请求变得易于管理,我创建了一个XmlHttpRequest类,如下所示: function XmlHttpRequest(inElement) { this.request = new XMLHttpRequest();

赏金提示:简单的问题是,如果是异步请求,为什么我不需要担心goGet在请求完成之前被删除呢

我有一个用PHP生成的表单,它生成了许多HTML行,我将它们称为条目。每个条目有两个选项,删除和编辑,每个选项可能需要创建零个或多个XMLHttpRequests

为了使处理请求变得易于管理,我创建了一个XmlHttpRequest类,如下所示:

function XmlHttpRequest(inElement) {
    this.request = new XMLHttpRequest();
    this.write = inElement;

    var self = this;
    this.request.onreadystatechange = function() {
        self.write.innerHTML = (self.request.readyState == 4) ? self.request.responseText : "Please wait…";
    }
}

XmlHttpRequest.prototype.post = function(inFile, inPost) {
    this.request.open("POST", inFile, true);
    this.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    this.request.send(inPost);
}
单击“删除”或“编辑”时,它们调用函数,其中之一是:

function getForm(inEntryId, inTemplateId) {
    var key = "form"+inEntryId;
    if (!requested[key]) {
        var goGet = new XmlHttpRequest(document.getElementById("hideOptions"+inEntryId));
        goGet.post("getForm.php", "id="+inEntryId+"&template="+inTemplateId);
    }
    requested[key] = true;
}
这似乎效果不错。然而,在写了这篇文章之后,我开始担心当执行以getForm结束时,goGet可能会在请求完成之前被删除,并且该过程可能无法在函数XmlHttpRequest内完成,即this.request.onreadystatechange=函数

这是否是我需要担心的事情,因此我必须与每个goGet保持某种全球联系


编辑:在使用它一段时间后,我意识到答案可能是否定的,在它完成请求之前,它没有被删除,我想知道的是为什么。另外,我决定删除关于原型的附带问题。你问这个问题是对的:根据通常的Javascript内存管理,goGet及其所有相关内容都应该被垃圾收集

然而,由于调用XMLHttpRequest并忘记它是XMLHttpRequest的一种非常常见的使用模式,因此在这些情况下,有一些特殊的规则阻止其垃圾收集

规格说明如下:

4.2垃圾收集

如果XMLHttpRequest对象的状态为,则不能对其进行垃圾收集 已打开并设置了发送标志,其状态为HEADERS\u RECEIVED,或 其状态为正在加载,并且已注册一个或多个事件侦听器 其类型为readystatechange、progress、abort、error、load、, 超时,然后加载结束

如果XMLHttpRequest对象在其连接时被垃圾收集 如果仍处于打开状态,则用户代理必须终止请求

还有:措辞略有不同

在实践中,似乎有些实现实际上可能会使XMLHttpRequests保留更长的时间。您可以在这里找到关于该主题的长时间讨论:

你问的问题很对:根据通常的Javascript内存管理,goGet及其所有相关内容都应该被垃圾收集

然而,由于调用XMLHttpRequest并忘记它是XMLHttpRequest的一种非常常见的使用模式,因此在这些情况下,有一些特殊的规则阻止其垃圾收集

规格说明如下:

4.2垃圾收集

如果XMLHttpRequest对象的状态为,则不能对其进行垃圾收集 已打开并设置了发送标志,其状态为HEADERS\u RECEIVED,或 其状态为正在加载,并且已注册一个或多个事件侦听器 其类型为readystatechange、progress、abort、error、load、, 超时,然后加载结束

如果XMLHttpRequest对象在其连接时被垃圾收集 如果仍处于打开状态,则用户代理必须终止请求

还有:措辞略有不同

在实践中,似乎有些实现实际上可能会使XMLHttpRequests保留更长的时间。您可以在这里找到关于该主题的长时间讨论:

goGet无法生存,但您的XmlHttpRequest实例可以生存 简单的答案是goGet在getForm调用结束时被垃圾收集,在这一点之后,您将无法使用goGet访问任何内容。然而,这只是一个变量,它临时保存了对内存中对象的引用,该对象是XmlHttpRequest的一个实例,用于触发post。由于下一步,实例结构本身仍将保留在内存中

内部浏览器进程也是代码,将保留引用 在调用post时(仍然在getForm中,而goGet存在),您将存储的XHR设置为Gong,这将触发内部浏览器进程来处理这些请求,但只有在goGet完成执行之后。因为XHR总是在调用它们的代码执行后触发,所以浏览器必须特别保持它们的活动状态,以便它们能够实际工作

因为XHR对象保持活动状态,所以已经定义的readystatechange处理程序也会保持活动状态,这是一个闭包,它通过self保存对XmlHttpRequest原始实例的引用

当XHR请求仍在处理时,readystatechange处理程序仍将存在,因此使用XmlHttpRequest创建的整个结构将保持活动状态,直到该闭包被销毁

有关此过程的信息性帖子可在此处找到:

还应该注意的是,垃圾收集往往不是即时的,它通常在计划的波中发生,所以即使 如果删除了对结构的所有引用,它仍可以在内存中保留一段未知的时间。然而,在这种情况下,这并不是让你的结构保持活力的原因

goGet无法生存,但XmlHttpRequest实例可以生存 简单的答案是goGet在getForm调用结束时被垃圾收集,在这一点之后,您将无法使用goGet访问任何内容。然而,这只是一个变量,它临时保存了对内存中对象的引用,该对象是XmlHttpRequest的一个实例,用于触发post。由于下一步,实例结构本身仍将保留在内存中

内部浏览器进程也是代码,将保留引用 在调用post时(仍然在getForm中,而goGet存在),您将存储的XHR设置为Gong,这将触发内部浏览器进程来处理这些请求,但只有在goGet完成执行之后。因为XHR总是在调用它们的代码执行后触发,所以浏览器必须特别保持它们的活动状态,以便它们能够实际工作

因为XHR对象保持活动状态,所以已经定义的readystatechange处理程序也会保持活动状态,这是一个闭包,它通过self保存对XmlHttpRequest原始实例的引用

当XHR请求仍在处理时,readystatechange处理程序仍将存在,因此使用XmlHttpRequest创建的整个结构将保持活动状态,直到该闭包被销毁

有关此过程的信息性帖子可在此处找到:

还应该注意的是,垃圾收集往往不是即时的,它通常发生在预定的波形中,因此即使删除了对结构的所有引用,它仍然可以在内存中停留未知的一段时间。然而,在这种情况下,这并不是让你的结构保持活力的原因


W3C XMLHttpRequests规范明确规定,XMLHttpRequest在[XMLHttpRequest级别1]中解释的某些情况下不能进行垃圾收集

因此,浏览器有责任确保垃圾收集不会发生在例如open XMLHttpRequests上。在没有深入了解细节的情况下,我注意到Chromes Heap Snapshot工具显示,即使在本地引用超出范围后,请求仍被许多全局对象引用。多年来,XMLHttpRequests中也出现了一些与内存泄漏相关的bug,我认为这可能是由于浏览器实现没有做到这一点

4.3垃圾收集 如果XMLHttpRequest对象的状态为,则不能对其进行垃圾收集 已打开并设置了发送标志,其状态为HEADERS\u RECEIVED,或 其状态为“正在加载”,且以下情况之一为真:

它注册了一个或多个类型为的事件侦听器 readystatechange、progress、abort、error、load、timeout或loadend

上载完成标志未设置且关联的 XMLHttpRequestUpload对象已注册一个或多个事件侦听器 其类型为进度、中止、错误、加载、超时或加载结束

如果XMLHttpRequest对象在其连接时被垃圾收集 如果仍处于打开状态,则用户代理必须终止请求


W3C XMLHttpRequests规范明确规定,XMLHttpRequest在[XMLHttpRequest级别1]中解释的某些情况下不能进行垃圾收集

因此,浏览器有责任确保垃圾收集不会发生在例如open XMLHttpRequests上。在没有深入了解细节的情况下,我注意到Chromes Heap Snapshot工具显示,即使在本地引用超出范围后,请求仍被许多全局对象引用。多年来,XMLHttpRequests中也出现了一些与内存泄漏相关的bug,我认为这可能是由于浏览器实现没有做到这一点

4.3垃圾收集 如果XMLHttpRequest对象的状态为,则不能对其进行垃圾收集 已打开并设置了发送标志,其状态为HEADERS\u RECEIVED,或 其状态为“正在加载”,且以下情况之一为真:

它注册了一个或多个类型为的事件侦听器 readystatechange、progress、abort、error、load、timeout或loadend

上载完成标志未设置且关联的 XMLHttpRequestUpload对象已注册一个或多个事件侦听器 其类型为进度、中止、错误、加载、超时或加载结束

如果XMLHttpRequest对象在其连接时被垃圾收集 如果仍处于打开状态,则用户代理必须终止请求


不用担心,它不会被垃圾收集。你可以在原型中使用第二个,但是你不能通过这种方式达到自我,你必须使用这个,但是因为

re没有冲突,切换应该不会有问题。@dandavis,我有预感不会有问题,因为我假设请求的时间比完成getForm的执行要长很多,但是什么可以防止它被垃圾收集呢?@dandavis,没有意识到你编辑了你的评论。我不知道编写这个.request.onreadystatechange=函数的语法作为原型是什么样子的嗯,也许我们不能在原型中这样做,至少不能完全这样做,因为它是一种初始化的东西,并且该方法通常属于构造函数的实例输出以外的东西。不过,我们可以将其存储在那里:this.request.onreadystatechange=this.onChange.bindthis;/*/*XmlHttpRequest.prototype.onChange=函数{this.write.innerHTML=this.request.readyState==4?this.request.responseText:请稍候…;};顺便说一下,我认为您对XmlHttpRequest和XmlHttpRequest的使用令人困惑。嗯,你真的应该找到一个更好更不同的名字,有人一定会在某个点上绊倒。即使是myXmlHttpRequest也会更好。它不会被垃圾收集,不用担心。您可以在prototype中使用第二个,但您无法通过这种方式访问self,您必须使用它,但既然没有冲突,切换应该不会有问题。@dandavis,我有一种预感,它不会,因为我假设请求所需的时间比完成getForm的执行要长得多,但是什么阻止它被垃圾收集?@dandavis,不知道你编辑了你的评论。我不知道编写这个.request.onreadystatechange=函数的语法作为原型是什么样子的嗯,也许我们不能在原型中这样做,至少不能完全这样做,因为它是一种初始化的东西,并且该方法通常属于构造函数的实例输出以外的东西。不过,我们可以将其存储在那里:this.request.onreadystatechange=this.onChange.bindthis;/*/*XmlHttpRequest.prototype.onChange=函数{this.write.innerHTML=this.request.readyState==4?this.request.responseText:请稍候…;};顺便说一下,我认为您对XmlHttpRequest和XmlHttpRequest的使用令人困惑。嗯,你真的应该找到一个更好更不同的名字,有人一定会在某个点上绊倒。甚至myXmlHttpRequest也会更好。规范引用+1作为证明。这在铬和壁虎身上进行了大量测试。这也是正确的答案。事实是-对于像XMLHttpRequest这样的主机对象,浏览器的DOM API可以很好地使用JS作为主机对象。谢谢你,现在可以用+1作为规范参考的证明。这在铬和壁虎身上进行了大量测试。这也是正确的答案。事实是-对于像XMLHttpRequest这样的主机对象,浏览器的DOM API可以很好地使用JS作为主机对象。谢谢,现在有意义谢谢,现在有意义谢谢,现在有意义谢谢,没有意识到内存泄漏,我必须调查一下。谢谢,没有意识到内存泄漏,我必须调查一下