【问题标题】:What is wrong with the delete portion of my API?我的 API 的删除部分有什么问题?
【发布时间】:2020-03-14 13:20:06
【问题描述】:

我正在学习网络编程课程,我们正在编写网络服务器 API。我目前已经实现了 POST 和 GET,但是在实现 DELETE 时遇到了一些麻烦。我在这里做错了什么?我希望能详细解释我做错了什么,因为我真的在努力学习这些材料(当然,除非它只是格式错误)。

还有很多部分还没有实现,所以我敢肯定有很多错误。大多数情况下,我关心的是 DELETE,以及我的代码中我不理解的任何其他明显内容。

我已将我的域名替换为 fakeDomainName.com

index.html 和 script.js 位于公共文件夹中。 start.js 在我的主目录中。

我们正在创建一个简单的投票类型 api 来练习,使用 Node.js 服务器和 MongoDB 数据库来存储信息。目前,POST 和 GET 正在按预期工作,但 DELETE 给了我这些错误:

spread.js:25 DELETE http://fakeDomainName.com:3010/api/candidates/undefined 500 (Internal Server Error)
(anonymous) @ spread.js:25
e.exports @ spread.js:25
e.exports @ spread.js:25
Promise.then (async)
r.request @ spread.js:25
r.<computed> @ spread.js:25
(anonymous) @ axios.min.js:477
deleteItem @ script.js:65
invokeWithErrorHandling @ vue.js:1855
invoker @ vue.js:2173
original._wrapper @ vue.js:7416

spread.js:25 Uncaught (in promise) Error: Request failed with status code 500
    at e.exports (spread.js:25)
    at e.exports (spread.js:25)
    at XMLHttpRequest.d.onreadystatechange (spread.js:25)
e.exports @ spread.js:25
e.exports @ spread.js:25
d.onreadystatechange @ spread.js:25
XMLHttpRequest.send (async)
(anonymous) @ spread.js:25
e.exports @ spread.js:25
e.exports @ spread.js:25
Promise.then (async)
r.request @ spread.js:25
r.<computed> @ spread.js:25
(anonymous) @ axios.min.js:477
deleteItem @ script.js:65
invokeWithErrorHandling @ vue.js:1855
invoker @ vue.js:2173
original._wrapper @ vue.js:7416

这是我在“start.js”中的代码,这是我用来启动服务器的代码。

const express = require('express');
const bodyParser = require("body-parser");

const multer = require('multer');
const upload = multer({
  dest: './public/images/',
  limits: {
    fileSize: 10000000
  }
});

const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: false
}));

app.use(express.static('public'));

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/voting', {
  useNewUrlParser: true
});

var candidateSchema = new mongoose.Schema({
  name: String,
  bio: String,
  numVotes: String,
});

var Candidate = mongoose.model('Candidate', candidateSchema);

//add a candidate to the list
    app.post('/api/candidates', async(req, res) => {
      console.log("initiated post request");
      const candidate = new Candidate({
        name: req.body.name,
        bio: req.body.bio,
        numVotes: req.body.numVotes,
      });
      this.addItem = candidate.data;
      try {
        await candidate.save();
      }
      catch (error) {
        console.log(error);
        res.sendStatus(500);
      }
    });

    // Get a list of all of the candidates.
    app.get('/api/candidates', async(req, res) => {
      console.log("initiated get request");
      try {
        let candidate = await Candidate.find();
        res.send(candidate);
      }
      catch (error) {
        console.log(error);
        res.sendStatus(500);
      }
    });

    //delete a candidate from the list
    app.delete('/api/candidates/:id', async(req, res) => {
      console.log("initiated delete request");
      Candidate.deleteOne({ _id: req.params.id }, function(err) {
        if (err) res.sendStatus(500);
        else {
          console.log(req.params.id, "deleted successfully");
          res.sendStatus(200);
        }
      });
    });

    //edit a candidate
    app.put('/api/candidates/:id', async(req, res) => {
      console.log("initiated put(edit) request");
      try {
        let candidate = await Candidate.findOne({ _id: req.params.id });
        candidate.name = req.body.name;
        candidate.bio = req.body.bio;
        candidate.numVotes = req.body.numVotes;
        candidate.save();
        res.sendStatus(200);
      }
      catch (error) {
        console.log(error);
        res.sendStatus(500);
      }
    });

    app.listen(3010, () => console.log('Server listening on port 3010!'));

这是我在 script.js 中的代码,它链接到我的 index.html 页面:

    var app = new Vue({
      el: '#app',
      data: {
        name: "",
        bio: "",
        numVotes: "",
        file: null,
        addItem: null,
        items: [],
        findName: "",
        findItem: null,
      },
      created() {
          this.getItems();
        },

      computed: {
        suggestions() {
          return this.items.filter(item => item.title.toLowerCase().startsWith(this.findTitle.toLowerCase()));
        }
      },

      methods: {

        async postItem(item) {
            console.log("initiated");
          try {
            let response = await axios.post('/api/candidates', {
              name: this.name,
              bio: this.bio,
              numVotes: this.numVotes,
            });
            this.addItem = response.data;
          }
          catch (error) {
            console.log(error);
          }
        },

        async getItems() {
          try {
            let response = await axios.get("/api/candidates");
            this.items = response.data;
            return true;
          }
          catch (error) {
            console.log(error);
          }
        },

        selectItem(item) {
          this.findName = "";
          this.findItem = item;
        },


        async deleteItem(item) {
          try {
            let response = axios.delete("/api/candidates/" + item._id);
            this.findItem = null;
            this.getItems();
            return true;
          } catch (error) {
            console.log(error);
          }
        },

        async editItem(item) {
          try {
            let response = await axios.put("/api/candidates/" + item._id, {
              name: this.findItem.name,
              bio: this.findItem.bio,
              numVotes: this.findItem.numVotes,
            });
            this.findItem = null;
            this.getItems();
            return true;
          } catch (error) {
            console.log(error);
          }
        },
      },

    });

最后,这是我在 index.html 中使用的代码:

<!DOCTYPE HTML>
<html>

<head>
    <title></title>

</head>

<body>

    <h2>Hello World</h2>

    <div id="app">
        <div>
            <div>
                <input v-model="name" placeholder="Name">
                <p></p>
                <input v-model="bio" placeholder="Bio">
                <p></p>
                <input v-model="numVotes" placeholder="Number of votes">
                <button @click="postItem">Upload</button>
                <button @click="deleteItem">Delete</button>

            </div>
            <div v-if="addItem">
                <h2>{{addItem.name}}</h2>
                <h2>{{addItem.bio}}</h2>
                <h2>{{addItem.NumVotes}}</h2>
            </div>
        </div>

        <h2>Candidates:</h2>
        <div v-for="item in items">
            <div @click="selectItem">
            <h2>Name: {{item.name}}</h2>
            <h2>Bio: {{item.bio}}</h2>
            <h2>Number of Votes: {{item.numVotes}}</h2>
            </div>
        </div>
    </div>

    <!--Vue and axios-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.2/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="/script.js"></script>

</body>

</html>

【问题讨论】:

  • 使用可以使用findOneAndDelete而不是deleteOne it ....因为if会先找到然后删除结果。
  • 我得到了同样的错误。除了函数名不同之外,语法是否相同?
  • 你可以在日志中看到

标签: node.js mongodb rest vue.js mongoose


【解决方案1】:

正如您在 url 中看到的,您没有得到参数 id,它显示为未定义 //fakeDomainName.com:3010/api/candidates/undefined 因此,如果您将作为 id 传递,它会给出错误,它也可以正常工作

//delete a candidate from the list
    app.delete('/api/candidates/:id', async(req, res) => {
      console.log("initiated delete request");
      Candidate.findOneAndDelete({ _id: req.params.id }, function(err) {
        if (err) res.sendStatus(500);
        else {
          console.log(req.params.id, "deleted successfully");
          res.sendStatus(200);
        }
      });
    });```

【讨论】:

  • 这对我来说仍然会导致同样的错误。我需要从 script.js 传递 id 吗?如果是这样,我该怎么做?
【解决方案2】:

我用邮递员测试了你的节点端。 “删除”没问题。但是正如您在错误本身中看到的那样
DELETE http://fakeDomainName.com:3010/api/candidates/undefined 参数item id 正在发送未定义,因此无法删除。

在您的POST 请求中(在服务器/节点端),您也许可以添加一个sendStatus(200) 以避免post 请求被挂起。此外,您可以在保存@987654326 的同时获取已保存项目的id @

像这样:

    app.post('/api/candidates', async(req, res) => {
  console.log("initiated post request");
  const candidate = new Candidate({
    name: req.body.name,
    bio: req.body.bio,
    numVotes: req.body.numVotes,
  });
  this.addItem = candidate.data;
  try {
      console.log("Await save...");
    let data = await candidate.save();
    console.log("Done");
    res.statusCode = 200;
    res.setHeader('content-type','application/json');
    res.end(JSON.stringify(data));
  }
  catch (error) {
    console.log(error);
    res.sendStatus(500);
  }
});

响应是这样的:

{
"_id": "5dd38cb16f47912b40a1deef",
"name": "Ken Adams",
"bio": "bio",
"numVotes": "10",
"__v": 0

}

【讨论】:

  • 谢谢。我用 console.log 进行了测试,它肯定是未定义的。我已经在尝试发送项目 ID,所以我想我一定是做错了什么。如何发送商品 ID?
  • 您可以将它作为参数发送到 index.html 中的“deleteItem”中。你试过了吗? (我在答案中提到了如何在您postnew 项目时获得一个,您还可以通过GET 请求获得项目的ID。
  • 如何从 GET 删除请求中访问项目 ID?
  • 这取决于您如何获取项目(我看到您正在显示要选择的项目列表,您如何填充该列表?),在您添加它之后,或者换句话说如何你知道要删除哪个项目吗?
  • 这是我的问题的中心。我不知道如何识别该项目,所以我可以删除它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
相关资源
最近更新 更多