【发布时间】:2013-08-13 04:20:02
【问题描述】:
我正在使用 SDK(以前称为 Jetpack)为 Firefox 开发插件。
在我的插件中,我需要通过 JSONP 请求访问远程服务器(由我控制)上的 PHP 脚本的一些数据,然后使用从服务器来更新某些网页元素。
在我的 main.js 文件中,我使用 page-mod 和 contentScriptFile 将 JQuery 库的副本和我自己的 javascript 文件注入到网页中。 我的 javascript 文件使用 JQuery 的“$.ajax”函数来访问远程 PHP 脚本。
问题:从未收到响应。
我偶然发现了这个 StackOverflow 问题,它涉及相同的问题: error in jsonp call ONLY FROM firefox-extension
我已经遵循了那里的一些建议,并通过指定我自己的回调更改了我的 $.ajax 请求,并使用“unsafeWindow.callback”将回调函数添加到我的文件中 - 我不完全理解发生了什么,但似乎 JQuery 获取的“窗口”引用与真正的底层窗口对象不同(我认为这种事情是由 XRayWrapper 隐形处理的,所以对此感到困惑)。
没关系。我得到一个传递给我的回调的参数(我已将参数标记为“数据”),其中包含整个服务器响应 - 我需要的一切。
问题是,当我之前在 .ajax 函数中使用 success: 时,“this”指的是 ajax 对象(我认为 - Javascript 初学者),因此我指的是页面元素想要使用响应数据进行更新。 我无法在自定义回调中访问“this”。
我发现即使我总是从服务器得到响应,并且我的回调触发,JQuery 报告错误 - 如果我指定 error:,那么这将触发。 如果我添加 complete:,它也会触发,但 success: 不会触发。
我认为我可以使用 :complete 代替我的自定义回调,但似乎当调用错误处理代码时,它会清除服务器响应 - 我无法完整访问它:(XHR 对象.responseText 属性在处理完成时为“未定义”:)。
所以,我对所有这一切的拼凑解决方案如下。我有我的自定义回调,它传递了完整的服务器响应。我将它存储在一个全局变量中。 我指定完成:-接下来(或以后)触发-然后从那里访问全局变量,但也可以通过“this”访问我想更新的页面元素。
这让我很担心,因为可能会快速连续发出多个 AJAX 请求,因此我的解决方案取决于响应处理没有“交错” - 换句话说,我正在做一个假设(我不知道是真的)当 JQuery 接收到响应时,它将在开始处理下一个接收到的响应之前触发该响应的所有事件处理程序。 如果不是这样,那么我存储在全局变量中的数据可能与我想成功使用它的页面元素不对应:。到目前为止,它似乎在测试中有效,但可能只是我很幸运。
(旁注:我也使用 QTip2,它是 AJAX 插件 - 也总是抛出错误,而不是无声的。但我发现我可以通过添加错误来抑制它:并设置 xhr.status = 0 -我会在下面发布一个sn-p)。
但这似乎是一种可怕而混乱的做事方式。我不明白为什么 JQuery 在成功接收到服务器响应时会认为出现错误。 而且它的错误处理会破坏这个响应非常不方便,这意味着我无法成功处理它:。
有人有更简洁的解决方案吗?提前谢谢你 - sn-ps 跟随(顺便说一下,这些问题仅在我在我的附加组件中执行所有这些时存在。如果我在独立页面/脚本中执行相同的操作,它执行时不会出错被提升,并且完全符合预期)。
unsafeWindow.callback = function(data)
{
MyGlobalServerResponseVariable = data;
}
$.ajax(
{
url: 'http://nottherealurl.com/',
type: 'GET',
data: params,
async: true,
cache: false,
contentType: "text/json; charset=utf-8",
dataType: 'jsonp',
crossDomain: true,
jsonpCallback: "callback",
complete: function(xhr, textStatus)
{
var data = MyGlobalServerResponseVariable;
this.PageElementIWantToUpdate.attr("title", data.somevalue);
...
}
...
}
QTip2 错误抑制:
error: function(xhr, status, error)
{
xhr.status = 0;
}
最后一点,与上述没有直接关系 - 当我在 Firefox 中执行“文件->打开文件”并选择一个网页时,我的插件没有执行。这是设计的吗?
【问题讨论】:
-
在我发现一些东西的同时,我开始着手开发 Chrome 的等价物。 Chrome 没有等效的 unsafeWindow,以前用于访问未沙盒化窗口的“黑客”在 27 版中变得无能为力。所以我似乎无法使用 AJAX/来自我的 Chrome 插件的 JSONP 请求。
-
但我完全不确定它会起作用。后来发现是Chrome的Cross Origin XMLHttpRequest:developer.chrome.com/extensions/xhr.html这是什么意思?我可以使用 JSON 而不是 JSONP 并且 STILL 跨域边界调用。这很好,因为我负责远程服务器 PHP 脚本,所以我可以有条件地让它返回 JSON 而不是 JSONP。
-
另外一点是,我没有回过头来意识到 Firefox 支持完全相同的东西:addons.mozilla.org/en-US/developers/docs/sdk/Firefox-24/… 所以我也可以在 Firefox 中做到这一点 - 并放弃我可怕的 JSONP 解决方案。
标签: jquery ajax firefox-addon jsonp firefox-addon-sdk