You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android模拟器连接Node.js后端时CRUD更新/删除操作失败问题

问题描述

我使用Android模拟器将App连接至运行在3000端口的Node.js后端,服务器地址配置为:

final serverUrl = 'http://10.0.2.2:3000';

App已实现CRUD功能,但每次尝试更新或删除条目时,代码中的异常都会被抛出,且条目未被修改或删除。


前端Dart核心代码

Future<List<Item>> fetchItems() async {
    final response = await http.get(Uri.parse('$serverUrl/api/v1/items'));

    if (response.statusCode == 200) {
      final List<dynamic> itemList = jsonDecode(response.body);
      final List<Item> items =
          itemList.map((json) => Item.fromJson(json)).toList();
      return items;
    } else {
      throw Exception('Failed to fetch items');
    }
  }

  Future<Item> addItem(String name) async {
    final response = await http.post(Uri.parse('$serverUrl/api/v1/items'),
        headers: {'content-type': 'application/json'},
        body: jsonEncode({'name': name}));
   if (response.statusCode == 200) {
    final dynamic json = jsonDecode(response.body);
    final Item item = Item.fromJson(json);
    return item;
   }else{
    throw Exception('Failed to fetch item');
   }
  }

  Future<void> updateItem(int id, String name) async {
    final response = await http.delete(
      Uri.parse('$serverUrl/api/v1/items/$id'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({"name": name}),
    );
    if (response.statusCode != 200) {
      throw Exception('Failed to update item');
    }
  }

  Future<void> deleteItem(int id) async {
    final response = await http.delete(Uri.parse('$serverUrl/api/v1/items/$id'));
    if (response.statusCode != 200) {
      throw Exception('Failed to delete item');
    }
  }

UI触发代码

IconButton(
                            icon: const Icon(Icons.edit),
                            onPressed: () {
                              dialog('Edit item', 'Edit', onPressed: () {
                                updateItem(item.id, nameController.text);
                                Navigator.pop(context);
                              });
                            },
                          ),



floatingActionButton: FloatingActionButton(
        onPressed: () {
          dialog('Add item', 'Item name', onPressed: () {
            addItem(nameController.text);
            Navigator.pop(context);
          });
        },
        tooltip: 'Add button',
        child: const Icon(Icons.add),
      )

后端Node.js接口代码

const express = require('express');
const app = express();
const port = process.env.port || 3000;

const itemList = [
    {id: 1, name: 'name here'},
];

app.put('/api/v1/items/:id', (req, res) => {
  let itemId = req.params.id;
  let updatedItem = {
    id: itemId,
    name: req.body.name
  }
  const index = itemList.findIndex(item => item.id === itemId);
  if(index !== -1){
    itemList[index] = updatedItem
    res.json(updatedItem);
  }else{
    res.status(404).json({message: 'Item not found'})
  }
})

app.delete('/api/v1/items/:id', (req, res) => {
    let itemId = req.params.id;
    let index = itemList.findIndex(item => item.id === itemId);
    if(index!== -1){
     let deletedItem = itemList.splice(index, 1);
      res.json(deletedItem[0])
    }else{
      res.status(404).json({message: 'Item not found'})
    }
})

问题原因及修复方案

1. 请求方法不匹配

前端updateItem方法错误使用了http.delete请求,但后端更新接口定义的是PUT方法,导致请求无法被正确处理。
修复:将updateItem中的请求方法改为http.put:

Future<void> updateItem(int id, String name) async {
  final response = await http.put(
    Uri.parse('$serverUrl/api/v1/items/$id'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode({"name": name}),
  );
  if (response.statusCode != 200) {
    throw Exception('Failed to update item');
  }
}

2. ID类型不匹配

后端从req.params.id获取的是字符串类型,而前端传入的是整数类型,使用===严格相等比较会导致找不到对应条目。
修复:后端将参数ID转为数字类型:

// 更新接口
let itemId = Number(req.params.id);
// 删除接口
let itemId = Number(req.params.id);

3. 后端未解析JSON请求体

后端缺少express.json()中间件,无法解析前端POST/PUT请求的JSON格式请求体,导致req.body.name为undefined。
修复:在定义接口前添加中间件:

app.use(express.json());

4. (可选)捕获异步操作异常

UI触发更新/删除时,建议添加异常捕获逻辑,避免App崩溃:

IconButton(
  icon: const Icon(Icons.edit),
  onPressed: () {
    dialog('Edit item', 'Edit', onPressed: () async {
      try {
        await updateItem(item.id, nameController.text);
        // 可在此处刷新列表
      } catch (e) {
        print(e); // 或提示用户操作失败
      }
      Navigator.pop(context);
    });
  },
),

内容的提问来源于stack exchange,提问作者Achievers Tv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 14:56:07