无法定义回调时使用angularjs JSONP

Posted

技术标签:

【中文标题】无法定义回调时使用angularjs JSONP【英文标题】:Using angularjs JSONP when callback cant be defined 【发布时间】:2013-10-22 21:24:36 【问题描述】:

我正在尝试使用 Angularjs 从 USGS 地震源中收集数据。通常,您需要将 ?callback=JSON_CALLBACK 添加到 URL 的末尾,以便 Angular 使用它,但是 USGS 提要不识别此选项。

我使用的 URL 是 http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojsonp,添加 ?callback=JSON_CALLBACK(例如 http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojsonp?callback=JSON_CALLBACK)会返回一个包装在名为 eqfeed_callback 的函数中的数据集。

有什么方法可以使用这些数据吗?我有一个 eqfeed_callback 函数,但它不在范围内,这使得使用 Angular 毫无意义。

这是我目前的代码:

function QuakeCtrl($scope, $http) 

    $scope.get_quakes = function() 
        var url = 'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojsonp';
        $http.jsonp(url)
    



function eqfeed_callback(data) 
    return data;

有什么方法可以让数据返回作用域,或者在内部使用 eqfeed_callback 函数?

【问题讨论】:

您是否反对只使用JSON?我冒昧地猜测,从 url 中删除 p 会使其成为纯 JSON,它确实如此。 可以,但是 USGS 没有启用 CORS,所以我得到了跨源错误。如果未启用 CORS,有没有办法使用 JSON?我的理解是这是服务器端设置,我不能修改。 哦:/ 猜你不能那样做;是的,这是一个服务器端设置。 【参考方案1】:

扩展@MichaelVanRijn 的回答:

为了维护“全球和平”,在需要的时候定义全局函数,然后立即取消它。

.controller('QuakeCtrl', function($window, $scope, $http) 
  $scope.get_quakes = function() 
    $window.eqfeed_callback = function(data)
      console.log("quake data", data)
    ;

    // load your jsonp data
    $http.jsonp('http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojsonp')
    .then(function(success) 
      console.log(success);
      $window.eqfeed_callback = null;
    , function(fail) 
      console.log(fail);
      $window.eqfeed_callback = null;
    )
  
)

【讨论】:

【参考方案2】:

另一种选择是在范围内定义 eqfeed_callback,如下所示:

function QuakeCtrl($scope, $http) 
    $scope.data = null;
    $scope.get_quakes = function() 
      var url = 'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojsonp';
      $http.jsonp(url)
    

    window.eqfeed_callback = function(data) 
      $scope.data = data
    

【讨论】:

太棒了!这样做。谢谢! 甚至:$window.eqfeed_callback ... 这只是使用全局变量的另一种方式。 @T.J.Crowder 如此真实,但我认为它使逻辑更到位:)【参考方案3】:

想到的唯一想法是(blech)使用全局,然后手动触发Angular更新,例如:

var callback$scope;
function QuakeCtrl($scope, $http) 

    $scope.get_quakes = function() 
        var url = 'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojsonp';
        callback$scope = $scope;
        $http.jsonp(url)
    



function eqfeed_callback(data) 
    if (callback$scope) 
        // 1. Use callback$scope here
        // 2. Set callback$scope to undefined or null
        // 3. Trigger an Angular update (since it won't be automatic)
    

不漂亮,但是……

【讨论】:

他可以只使用JSON 而不是JSONP 请求,这比这更简单。另外,它不需要是$scope = callback$scope 吗?甚至$http.jsonp.call(callback$scope, [url])? @Fred:他不能使用 JSON,因为要这样做,他必须使用 ajax,这将是一个跨域请求。 SOP 不允许这样做(当然,除非地震.usgs.gov 支持 CORS,并且用户正在使用支持它的浏览器,并且他处理了整个 IE9 和更早版本的问题)。

以上是关于无法定义回调时使用angularjs JSONP的主要内容,如果未能解决你的问题,请参考以下文章

javascript Angularjs回调服务(方法链接和自定义回调)

AngularJS自己定义标签加入回调函数eval()

如何自定义设置 angularjs jsonp 回调名称?

“未捕获的类型错误:在 angularJS/NodeJS 中使用条带支付方法 Stripe.charges.create() 时无法读取未定义的属性‘创建’”

在angularjs中获取`Unexpected token :`但不能使用回调

在 AngularJS 中设置 JSONP 回调函数