JSONP - 触发完成,成功,错误Ajax调用

时间:2014-12-16 19:32:23

标签: javascript jquery ruby-on-rails ajax

好吧,我已经和它斗争了几个小时。

我手动返回不同的状态代码...如果状态为200则成功并完成。

但是我尝试了很多400代码示例:400,401,403,404来触发错误并永远不会让它工作

当我传递除状态200以外的任何内容时,它只会重新加载页面...但如果状态为200,它将登录并提醒完成...

(function( $ ) {
  var Core = Core || {};
  Core = {
    init: function (){
    },
    api: {
      submit: function( ajax_url, ajax_data, callback ){
        var auth_token = '';
        if( Core.auth.isAuthenticated() ) {
          auth_token = Core.auth.authToken.get();
        }
        $.ajax({
          type: "GET",
          dataType: "jsonp",
          // test
          url: "http://192.168.1.65:3000/" + ajax_url,
          // live
          //url: "http://www.customsite.com/" + ajax_url,
          cache: false,
          //data: ajax_data,
          data: 'auth_token='+ auth_token + '&' + ajax_data,
          success: function(data) {
            if(typeof callback.onSuccess == 'function'){
              callback.onSuccess.call(this, data);
            }
          },
          error: function(data){
            if(typeof callback.onError == 'function'){
              callback.onError.call(this, data);
            }
          },
          complete: function(data){
            if(typeof callback.onComplete == 'function'){
              callback.onComplete.call(this, data);
            }
          }
        });
      }
    }
  };

  $( Core.init );
  window.Core = Core;
})(jQuery);

表格提交

authenticate: {
  onSubmit: function(form_obj) {
    var ajax_url = form_obj.attr('action'),
        ajax_data = form_obj.serialize();
    Core.api.submit( ajax_url, ajax_data,
      {
        onSuccess: Core.login.authenticate.onSuccess,
        onError: Core.login.authenticate.onError,
        onComplete: Core.login.authenticate.onComplete
      }
    );
  },

  onSuccess: function(data) {
    Core.auth.authToken.set(data.access_token, 30);
    window.location = 'index.html';
  },

  onError: function(data) {
      alert('ERROR');
  },


  onComplete: function(data) {
      alert('Complete');
  }
}

rails应用程序:

  def create
    resource = User.find_for_database_authentication(:email => params[:user][:email])
    if resource.valid_password?(params[:user][:password])
      resource.reset_authentication_token!
      render :json => {:access_token => resource.authentication_token, :token_type => "persistant"}, :callback => params[:callback], :status => 200
    else
      render :json => {:error => "invalid_grant"}, :callback => params[:callback], :status => 404
    end
  end

1 个答案:

答案 0 :(得分:1)

您正在制作JSONP请求,这是一种跨域" Ajax"的形式。请阅读StackOverflow上的What is JSONP all about?了解其工作原理。

简短说明:JSONP使用<script src="your URL here"></script>标记来触发JavaScript文件的下载。由于它是常规的SCRIPT元素,因此任何非200 HTTP响应都会触发&#34; onerror&#34;在浏览器中回调该元素。您的Rails应用程序的类似REST的响应正在打破浏览器上的错误处理。 jQuery中的JSONP请求具有非常有限的错误处理。如果发出JSONP请求,您始终需要呈现200 OK响应。

如果你想要类似REST的响应,我建议用一些额外的JSON包装你的实际HTTP响应:

{
    "response": {
        "status": 401,
        "data": {
            ...
        }
    }
}

然后您的成功处理程序必须智能地解析响应:

success: function(data) {
    if (data.response.status === 200 && callback.onSuccess) {
        callback.onSuccess.call(this, data.response.data);
    }
    else if (data.response.status >= 400 && callback.onError) {
        callback.onError.call(this, data.response.data.error);
    }

    if (callback.onComplete) {
        callback.onComplete.call(this, data.response.data);
    }
}


authenticate: {
  onSubmit: function(form_obj) {
    var ajax_url = form_obj.attr('action'),
        ajax_data = form_obj.serialize();
    Core.api.submit( ajax_url, ajax_data,
      {
        onSuccess: Core.login.authenticate.onSuccess,
        onError: Core.login.authenticate.onError,
        onComplete: Core.login.authenticate.onComplete
      }
    );
  },

  onSuccess: function(data) {
    Core.auth.authToken.set(data.access_token, 30);
    window.location = 'index.html';
  },

  onError: function(data) {
      alert(data);
  },

  onComplete: function(data) {
  }
}

对Rails控制器的更改:

def create
  resource = User.find_for_database_authentication(:email => params[:user][:email])

  if resource.valid_password?(params[:user][:password])
    resource.reset_authentication_token!

    render :json => {
      :response => {
        :status => 200,
        :data => {:access_token => resource.authentication_token, :token_type => "persistant"}
        }
      } 
    }, :callback => params[:callback]


  else
    render :json => {
      :response => {
        :status => 401,
        :data => {
          :error => "invalid_grant"
        }
      }
    }, :callback => params[:callback]
  end
end