HTTP请求多浏览器问题

18

我正在使用 laravel 5.1angularJs 进行开发。

当用户点击一个按钮时,我想发送一个destroy请求将其从数据库中删除,然后在完成操作后发送一个get请求以获取新的数据。

所以,我将我的方法附加到按钮的ng-click事件上,这样可以触发该方法。

然后我运行.destroy请求。在.destroy.then()方法内,我想调用另一个具有.get请求的方法。

这在Safari中完美运行,但在Chrome或Firefox中无法正常工作。

以下是控制器的代码,被调用以删除的方法为deleteOpportunity()

$scope.getOpportunities = function()
    {
        UBOService.get()
            .then(function successCallback(responsed) {
                $scope.opportunities = responsed.data;
            }, function errorCallback(response) {
                $scope.error = response;
            });
    }
$scope.deleteOpportunity = function()
    {

                UBOService.destroy($scope.activeItem.id)
                    .then(function successCallback(response) {
                        $scope.getOpportunities();

                        return false;
                    }, function errorCallback(response) {
                        $scope.error = response;
                    });

    }

我的服务代码:

app.service('UBOService', function($http) {

    return {
        get : function() {
            return $http.get('/api/user-booked-opportunities');
        },

        destroy : function(id) {

            return $http.delete('/api/user-booked-opportunities/' +  id);
        }
    }
})

我是不是做错了什么?我有没有遗漏什么?Safari如何与这段代码交互,使其能够正常工作?


1
有任何异常被写入控制台吗?如果没有,它是否甚至到达了 $http.get 调用? - cDecker32
1
你好!我刚刚完成了一个使用L5.1和AngularJS 1.47的项目。我可以建议你在"then"块之后使用.finally()而不是",function()"。此外,我建议你在删除某些内容后不要进行任何http调用,而是从存储数据的变量中删除这些对象。如果你需要进一步的解释,我可以在另一个评论中给你更多的信息和代码示例。 :) - Cowwando
1
Safari浏览器有什么问题?删除请求?还是获取请求?或者是按钮点击本身?此外,您在Laravel部分中使用的控制器类型是什么?控制台中是否有任何错误? - Keerthi Kumar P
你可能会遇到其他问题,但为了减少一些调用,当你销毁一个机会时,你可以返回新的机会列表,这样你就不必进行单独的调用。或者我刚刚读到@Cowwando的评论,按照他说的做,那是我通常的做法。 - ribsies
把分号放在} $scope.deleteOpportunity = function() {这里有帮助吗?像这样:}; $scope.deleteOpportunity = function() { - Mark Schultheiss
显示剩余2条评论
3个回答

3

从你发布的参数很难判断,但仅凭你说这在Safari中完美运行,但在Chrome或Firefox中却不行,听起来像是CORS问题。

Firefox和Chrome对跨域请求有不同的要求,与Safari不同。你的Laravel api端点是否位于与Angular应用相同的位置?API返回了哪个"Access-Control-Allow-Origin"头文件?

尝试添加以下内容到Laravel中,看看是否能使该块在这些浏览器中始终如一:

App::before(function($request) {
  // Enable CORS 
  // In production, replace * with http://yourdomain.com 
  header("Access-Control-Allow-Origin: *");
  header('Access-Control-Allow-Credentials: true');

  if (Request::getMethod() == "OPTIONS") {
    // The client-side application can set only headers allowed in Access-Control-Allow-Headers
    $headers = [
      'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, DELETE',
      'Access-Control-Allow-Headers' => 'X-Requested-With, Content-Type, X-Auth-Token, Origin, Authorization'
    ];
    return Response::make('You are connected to the API', 200, $headers);
  }
});

(^ source)


2

我猜这是一个CORS问题。此外,如果您将客户端与服务器端解耦,通常会出现此问题。您需要创建一个前置中间件来处理此类问题。

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
  /**
  * Handle an incoming request.
  *
  * @param  \Illuminate\Http\Request  $request
  * @param  \Closure  $next
  * @return mixed
  */
 public function handle($request, Closure $next)
 {
    /** 
    * The access control allow origin and 
    * allow credential is set to * and true 
    * because i allow request from different domains
    * to hit the server
    */
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Credentials: false');
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization');

    if ($request->getMethod() == "OPTIONS") {
        $headers = array(
            'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
            'Access-Control-Allow-Headers'=> 'X-Requested-With, content-type',);
        return Response::make('', 200, $headers);
    }

    return $next($request);
 }
}

在 Angular 方面,添加以下配置块:
app.config(['$httpProvider', function ($httpProvider) {

  $httpProvider.defaults.useXDomain = false;
  $httpProvider.defaults.withCredentials = false;
  delete $httpProvider.defaults.headers.common['X-Requested-With'];

}]);

0
如果在successCallbackerrorCallback中返回一个值,则返回的值将用于解析promise。 尝试定义一个$q.deferred,该deferred将在获取数据时通过get $http成功得到解决。
$scope.deleteOpportunity = function() {
            var deferred = $q.defer();

            UBOService.destroy($scope.activeItem.id)
                .then(function successCallback(response) {
                    UBOService.get().then(function(response){
                        $scope.opportunities = response.data;
                        deferred.resolve(response.data);
                    };
                }, function errorCallback(response) {
                    $scope.error = response;
                });
        return deferred.promise;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接