【问题标题】:Can't call $http.get() more than once不能多次调用 $http.get()
【发布时间】:2017-03-21 08:33:40
【问题描述】:

完整修改问题

由于这个问题已经演变成完全不同的东西,我想最好还是从头开始解释当前的情况。

我正在尝试使用 Node、Express、MongoDB 和 Angular 创建一个简单的留言板。

我有一个 get 和 post 功能,它在服务器端似乎工作正常,我没有收到任何错误,并且我的数据正在添加到数据库/从数据库中检索。

问题在于我的客户端 getMessages() 函数。

在正常情况下,我想在网站初始化时和发布消息后调用 getMessages()。但为简单起见,我创建了一个按钮,按下时调用“getMessages()”。

当我第一次按下此按钮时,会发出一个 GET 请求,并检索我的所有消息并显示在视图中。

但是当我发布消息并再次点击“get-messages-button”时,没有发送新的 GET 请求,并且该函数返回旧列表(使用第一个也是唯一的 GET 检索的列表-请求)

我已经坚持了 3 天了,我真的不明白我做错了什么。正在调用 getMessages() 函数,但似乎它将第一个 GET 请求中的“response.data”存储在某处并立即返回相同的数据,而没有机会发送新的 GET 请求。

代码:

控制器

(function() {
'use strict';

angular
.module('app')
.controller('MainController', mainController);

function mainController(navigationFactory, $http, $timeout, apiFactory, $scope) {

    var that = this; // jshint ignore: line

    function init() {
        //that.getMessages();
    }

    that.getMessages = function() {
        return apiFactory.getMessages().then(function(messages) {
            that.messages = messages;

        });
    }

    that.postMessage = function() {

        apiFactory.postMessage(that.message).then(function(response) {
            console.log('Posted from controller', response);               
        }).catch(function(e) {
            console.log(e);
        });

    }

    init();   
}
})();

服务

(function() {
'use strict';

angular
    .module('app')
    .factory('apiFactory', apiFactory);

function apiFactory($interval, $localStorage, $sessionStorage, $http) {

    var factory = {};

    factory.postMessage = function(message) {
        return $http.post('http://localhost:5000/api/message', {msg: message}).then(function(response) {
                return response;
        });       
    }

    factory.getMessages = function() {
        var promise = $http.get('http://localhost:5000/api/message').then(function(response) {
                console.log('data:', result.data); //Immediately returns old list without sending new GET request
                return response.data;
        });    

        return promise;        
    }

    return factory;
}

})();

Server.js(以防万一它还是我的服务器端代码)

var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');


var Message = mongoose.model('Message', {
    msg: String
});
var app = express();


app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
    next();
})

app.get('/api/message', GetMessages);

app.post('/api/message', function(req, res) {
    console.log(req.body);

    var message = new Message(req.body);
    message.save(function(err) {
        if(err) {
            console.log(err);
        } else {
            res.status(200).send('Message added');
        }
    }); 
})

function GetMessages(req, res) {
    console.log('Getting messages from server');
    Message.find({}).exec(function(err, result) {
        if(err) {
            return res.status(500).send(err);
        }
        return res.status(200).json(result);
    });

    console.log('Got messages from server');
}

mongoose.connect("mongodb://localhost:27017/mydb", function(err, db) {
    if(!err) {
        console.log("Connected to mongoDB!");   
    }
})

var server = app.listen(5000, function() {
    console.log('listening on port ', server.address().port);
})

更新

这可能有助于说明问题到底是什么。

当我按下视图上的按钮时,我有一个函数被调用:

    that.getMessages = function() {
         $http.get('http://localhost:5000/api/message'); // <-- Only happens once
         console.log('get request sent'); // <-- Gets logged everytime 
    };

我所做的只是向我的服务器发送一个获取请求。还没有任何承诺。 第一次按下按钮时,我可以在调试器网络选项卡中看到一个 GET 请求,该请求的状态为 304,并且响应了我的消息数组。

现在,当我第二次按下按钮时,没有发出 GET 请求。我可以记录消息,所以我知道我的函数正在被调用,但它似乎忽略了我的 $http.get()...

【问题讨论】:

  • 我看不到您在发帖后尝试在哪里再次获取消息。
  • 对不起,为了清楚起见,我将其添加到代码中。我之前删除了它,因为它不起作用。
  • 您已对该问题进行了 7 次更新。问题的当前状态是什么?另外请更新问题的标题。该问题似乎与将数据应用于范围无关。问题似乎在于在 POST 之后对 GET 操作进行排序。
  • 是的,与当前的答案讨论后变得很清楚,如果您有时间阅读它,您可能会明白。但我会更改帖子和标题以使其更清晰。

标签: angularjs node.js express asynchronous mean-stack


【解决方案1】:

在您发布新消息后,您的代码会立即收到消息。所以你不能保证第二个请求会在第一个请求之后被服务器处理。它们很有可能会同时处理。您需要在帖子处理完毕后获取消息,即当对第一个请求的异步响应返回时。

因此,首先,您需要能够知道发布成功的时间。因此,您需要返回 http 承诺,以了解它是已解决还是被拒绝:

factory.postMessage = function(message) {
    return $http.post('http://localhost:5000/api/message', {msg: message});
}

那么你需要在发帖成功后得到消息:

that.postMessage = function() {
    apiFactory.postMessage(this.message).then(function() {
        that.getMessages();
    });
}

【讨论】:

  • 谢谢!听起来很合乎逻辑。不幸的是,我的观点在发布消息后仍然没有更新......我仍然需要刷新。
  • 我尝试在 .then() 函数中登录到控制台,但看起来它从不调用 .then()
  • 表示发帖不成功。查看您的浏览器开发工具,在网络选项卡中,您得到的响应是什么。
  • 但是帖子确实成功了,因为消息被插入到数据库中。在我的网络选项卡中,我发送状态为 200 的帖子,但响应选项卡为空编辑:它没有状态 200,但状态未决,最终失败。
  • 啊,等了足够长的时间后,我突然收到这个错误:POST localhost:5000/api/messagenet::ERR_EMPTY_RESPONSE 也许我没有在帖子中发送正确的回调?
猜你喜欢
  • 2021-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 2018-08-28
  • 1970-01-01
  • 1970-01-01
  • 2017-06-02
相关资源
最近更新 更多