2016-03-02 77 views
17

Buduję w laravel 5.1 przy użyciu angularJs.Http żąda problemów z wieloma przeglądarkami

Gdy użytkownik kliknie przycisk, chcę wysłać destroy request, aby usunąć go z bazy danych, a następnie po jego zakończeniu wysłać get request, aby uzyskać nowe dane, które zostały usunięte.

Więc podłączyłem moją metodę do zdarzenia ng-click na przycisku, działa to, trafia w metodę.

Następnie uruchomię .destroy request. Wewnątrz metody .then() z tego .destroy chcę następnie wywołać inny sposób, który ma .get request.

Działa to doskonale w Safari, ale nie działa w przeglądarce Chrome ani Firefox.

Here is my code for the controller, metoda, która jest wywoływana przyciskiem kliknij, aby usunąć to 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; 
        }); 

    } 

Moje kod usługi:

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); 
     } 
    } 
}) 

Czy robię coś źle? Czy jest coś, czego mi brakuje? W jaki sposób Safari współpracuje z tym kodem inaczej, co sprawia, że ​​działa?

+1

Czy są jakieś wyjątki zapisywane na konsoli? Jeśli nie, to czy nawet dostaje się do wywołania $ http.get? – cDecker32

+1

Cześć! Właśnie skończyłem projekt z L5.1 i AngularJS 1.47. Czy mogę zaproponować ci użycie .finally() po twoim "wtedy" bloku zamiast ", function()". Dodatkowo chciałbym zasugerować, abyś nie wykonywał żadnych połączeń HTTP po usunięciu czegoś, ale usunięciu tych obiektów ze zmiennej, w której przechowujesz swoje dane.Jeśli chcesz uzyskać dodatkowe wyjaśnienia, mogę podać więcej informacji i przykładów kodu w oddzielnym komentarzu. :) – Cowwando

+1

Co nie działa w Safari? Żądanie usunięcia? lub żądanie otrzymania? lub kliknięcie przycisku samo w sobie? Również jakiego typu kontroler używasz w swojej części laravel? Jakieś błędy w konsoli? –

Odpowiedz

3

Trudno oszacować na podstawie opublikowanych parametrów, ale w oparciu o to, że działa to doskonale w Safari, ale nie działa w Chrome lub Firefox, wydaje się, że może to być problem z CORS.

Firefox i Chrome mają różne wymagania dla żądań o różnych pochodzeniach niż Safari. Czy Twój punkt końcowy apara Laravel dla tej akcji destroy znajduje się w tym samym miejscu co aplikacja Angular? Co nagłówek Access-Control-Allow-Origin powraca do interfejsu API?

Spróbuj dodać coś takiego do pliku laravel i zobaczyć, czy to sprawia, że ​​ten blok spójne tych przeglądarek:

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

Chyba jego CORS problem. Co więcej, ten problem zwykle występuje, jeśli oddzielisz stronę klienta od strony serwera. Musisz utworzyć przed oprogramowaniem pośredniczącym, aby poradzić sobie z takimi problemami.

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); 
} 
} 

A na kątowym stronie rzeczy dodać ten blok konfiguracyjny

app.config(['$httpProvider', function ($httpProvider) { 

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

}]); 
0

Jeśli zwróci wartość w successCallback lub errorCallback, zwrócona wartość będzie używana do rozwiązania promise. Spróbuj zdefiniować $q.deferred, które zostaną rozwiązane po uzyskaniu $ http sucess z danymi.

$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; 
}