对于我的项目,我需要使用JSONP对(远程)API进行多次调用以处理API响应。所有调用都使用相同的回调函数。所有调用都是使用JavaScript在客户端动态生成的。
问题如下:如何将其他参数传递给该回调函数,以便告诉函数我使用的请求参数。因此,例如,在以下示例中,我需要myCallback
函数来了解id=123
。
<script src="http://remote.host.com/api?id=123&jsonp=myCallback"></script>
有没有办法实现这一点,而无需为每个调用创建单独的回调函数?一个vanilla JavaScript解决方案是首选。
修改:
在第一个评论和答案之后,出现了以下几点:
答案 0 :(得分:10)
您的选择如下:
以下是第三个选项的示例。
您可以使用闭包来跟踪变量,但由于您可以同时在飞行中进行多个JSON调用,因此您必须使用动态生成的全局可访问函数名称,该函数名称对于每个连续的JSONP都是唯一的呼叫。它可以像这样工作:
假设您为JSONP生成标记的函数是这样的(您可以替换现在正在使用的任何内容):
function doJSONP(url, callbackFuncName) {
var fullURL = url + "&" + callbackFuncName;
// generate the script tag here
}
然后,你可以在它之外有另一个功能:
// global var
var jsonpCallbacks = {cntr: 0};
function getDataForId(url, id, fn) {
// create a globally unique function name
var name = "fn" + jsonpCallbacks.cntr++;
// put that function in a globally accessible place for JSONP to call
jsonpCallbacks[name] = function() {
// upon success, remove the name
delete jsonpCallbacks[name];
// now call the desired callback internally and pass it the id
var args = Array.prototype.slice.call(arguments);
args.unshift(id);
fn.apply(this, args);
}
doJSONP(url, "jsonpCallbacks." + name);
}
你的主代码会调用getDataForId()
,传递给它的回调将传递id值,然后是JSONP对函数的其他参数:
getDataForId(123, "http://remote.host.com/api?id=123", function(id, /* other args here*/) {
// you can process the returned data here with id available as the argument
});
答案 1 :(得分:1)
有一种更简单的方法。 在“?”之后将参数附加到您的网址。并在回调函数中访问它,如下所示。
var url = "yourURL";
url += "?"+"yourparameter";
$.jsonp({
url: url,
cache: true,
callbackParameter: "callback",
callback: "cb",
success: onreceive,
error: function () {
console.log("data error");
}
});
回调功能如下
function onreceive(response,temp,k){
var data = k.url.split("?");
alert(data[1]); //gives out your parameter
}
注意:如果URL中已有其他参数,则可以在URL中以更好的方式附加参数。我在这里展示了一个快速的解决方案。
答案 2 :(得分:0)
由于我似乎无法评论,我必须写一个答案。我已按照jfriend00的说明处理了我的情况,但在我的回调中没有收到服务器的实际响应。我最终做的是:
var callbacks = {};
function doJsonCallWithExtraParams(url, id, renderCallBack) {
var safeId = id.replace(/[\.\-]/g, "_");
url = url + "?callback=callbacks." + safeId;
var s = document.createElement("script");
s.setAttribute("type", "text/javascript");
s.setAttribute("src", url);
callbacks[safeId] = function() {
delete callbacks[safeId];
var data = arguments[0];
var node = document.getElementById(id);
if (data && data.status == "200" && data.value) {
renderCallBack(data, node);
}
else {
data.value = "(error)";
renderCallBack(data, node);
}
document.body.removeChild(s);
};
document.body.appendChild(s);
}
基本上,我将goJSONP和getDataForUrl压缩为1个函数,该函数编写脚本标记(并在以后删除它)以及不使用“unshift”函数,因为这似乎从args数组中删除了服务器的响应。所以我只是提取数据并使用可用的参数调用我的回调。这里的另一个不同之处是,我重新使用回调名称,我可能会将其更改为带有计数器的完全唯一的名称。
现在缺少的是超时处理。我可能会启动一个计时器并检查是否存在回调函数。如果它存在,它没有自行删除,所以它是一个超时,我可以采取相应的行动。
答案 3 :(得分:-1)
现在已经有一年了,但我认为jfriend00在正确的轨道上,虽然它比所有更简单 - 使用闭包仍然,只是,在指定回调时添加参数:
http://url.to.some.service?callback=myFunc( 'OPTA')
http://url.to.some.service?callback=myFunc( 'optB')
然后使用闭包传递它:
function myFunc (opt) {
var myOpt = opt; // will be optA or optB
return function (data) {
if (opt == 'optA') {
// do something with the data
}
else if (opt == 'optB') {
// do something else with the data
}
}
}