开发者问题收集

为什么我不能返回$.ajax结果但是可以返回$http.post结果?

2016-03-17
165

我有 2 个返回语句:

return $http.post({ 
    url: CHEAPWATCHER.config.domain + 'api/Authenticate',
    contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
    data: data
});

return $.ajax({
    type: 'POST',
    url: CHEAPWATCHER.config.domain + 'api/Authenticate',
    data: data
}).done(function (result) {
    console.log('logged successfuly');
}).fail(function (result) {
    console.log('loging failed');
});

以及使用 API 方法的 background.js 函数:

// REGISTER API COMMAND LISTENER
chrome.runtime.onConnect.addListener(function (port) {
    port.onMessage.addListener(function (request, portInfo) {
        // Globally accessible function to execure API calls
        CHEAPWATCHER.executeApiCall = function (request, senderId) {
            var originalRequestMethod = request.method;
            //Dinamically call API method
            CHEAPWATCHER.api[request.method](request, senderId).then(function (response) {
                port.postMessage(response);
            }, function (error) {
                port.postMessage(error);
            });
        };
        CHEAPWATCHER.executeApiCall(request, request.sender);
    });
});

因此,当我运行我的 chrome 扩展程序时,我当然会注释掉其中一个,但关键是它们都返回相同的对象类型 jqXHR,如果我使用 $http.post,它会给出以下错误:

Error in event handler for (unknown): TypeError: Cannot read property 'error' of null

以及

POST chrome-extension://cmakfpdagfeiefcmmpmhjrtyhonmgnbi/background/[object%20Object] net::ERR_FILE_NOT_FOUND

而当我使用 $.ajax 时,它可以工作,我得到了我需要的令牌,但它给出了这个错误:

Error in event handler for (unknown): TypeError: Cannot read property 'error' of null

之后我的扩展程序无法继续工作。昨天我问了为什么 $.ajax 会给我这个错误,我得到了答案,因为我无法返回 jqXHR 类型,但如果我使用

return $http.post(CHEAPWATCHER.config.domain + 'api/Authenticate', data);

一切都很好,只是 post 方法希望我给他 grant_type=password 和 Content-Type application/x-www-form-urlencoded,所以这就是我使用 $http.post([settings]) 结构的原因。

有人可以解释一下它们是如何工作的,以及为什么我会收到这些错误吗?也许我错误地使用了 post 方法,或者我需要声明更多我不知道的东西?

2个回答

您没有正确使用 $http.post 。此方法采用 3 个参数,而不是像这样的一个对象:

return $http.post(
   CHEAPWATCHER.config.domain + 'api/Authenticate',
   transformDataToUrlEncoded(data),
   {contentType: 'application/x-www-form-urlencoded; charset=UTF-8'}
});

如您所见,我放置了一个 transformDataToUrlEncoded。由于 angular 仅在 JSON 中序列化,因此他不会主动将 javascript 对象转换为 urlencoded。


来自主题之外的旧答案

$http.post 返回一个您可以使用 .then 的承诺。 Angular 承诺是可变的,这意味着您可以反复执行 .then().then().then() 以对结果进行多层处理。当然,您不需要经常这样做。我想说几乎从不超过 2 级:

  1. 处理来自服务器的结果并在服务层中格式化数据
  2. 在控制器层中使用结果

我不太了解 JQuery,但我猜它不能像 angular 那样链接。

您可能可以做到

.done().fail()

因为 .done 返回的对象可以执行 .fail(),但不能

.done().done(). 

因为 .done 返回的对象没有 .done() 方法。

最后,.fail() 是终止点:它不返回任何内容,因此您返回空值。


Walfrat
2016-03-17

经过大量的谷歌搜索和思考,我找到了解决方案,也许有一天它会对某人有所帮助。我没有使用 $html.post() 和 $.ajax() 方法,而是按照 @Walfrat 和 @TheMadDeveloper 的建议将数据转换为 x-www-form-urlencoded,因此我的代码现在完美地运行,如下所示:

return $http({
    method: 'POST',
    url: CHEAPWATCHER.config.domain + 'api/Authenticate',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    transformRequest: function (obj) {
        var str = [];
        for (var p in obj)
            str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
            return str.join("&");
        },
        data: data
    }).success(function (result) {
            console.log(result);
});

谢谢大家的帮助!!!

Nikas Žalias
2016-03-17