鸿蒙期末项目(4)

day4

页面的设计与编写基本完成,接下来使用我们之前搭建好的服务器与相关的网络接口将鸿蒙中的逻辑真正实现一下。

在实现购物车页面展示功能时,使用了如下代码:

getCartList(uid: number): Promise<CartItem[]> {
    return new Promise((resolve, reject) => {
        axios.get(
            `${this.baseUrl}/cart?uid=${uid}`
        )
            .then((resp) => {
            resolve(resp.data)
        })
            .catch((error) => {
            reject(error);
        })
    })
}

结果页面并未加载成功,日志显示错误:

随后通过postman测试服务端,显示返回结果为:

与CartItem类属性进行对比

并未发现差错。

进一步通过console.log发现,错误信息并非来自于axios请求,而是在调用model方法的.catch中被捕获的。这时服务器响应的数据已经正确被axios接收到了。

所以问题应当出现在调用的部分:

aboutToAppear() {
    CartModel.getCartList(CommentConstant.user.id)
        .then((list) => {
        this.productList = list;
        this.evalData(this.productList);
    })
        .catch((error) => {
        console.log(error);
    })
}

在一个偶然的巧合下,我将 this.evalData(this.productList); 注释掉,随后报错消失了。随后我用注释法(注释掉一部分代码看是否还报错)找到了 CartItem 类下的 getProduct() 方法。我使用 new CartItem().gerProduct() 加控制台输出的方式证明了这个方法 的清白 ,然而为什么通过服务器传过来的对象调用这个方法却会报 TypeError 的错呢?

最后的解决办法是从服务器接收数据的时候新创建一个对象,然后把接收对象的属性一条一条放到新对象中在使用。

推测可能的错误原因是,服务器传过来的这个对象仅仅“虚有其表”,仅仅包含了这个类的属性,却没有绑定这个类的方法,所以当尝试调用这个虚有其表的对象的方法时,编译器不会报错,但运行时抛报无法调用的异常。(也许与router传对象参数也无法使用的原因类似?)

最后页面成功显示了数据:

值得一提的是,删除一项时,我最初的想法是将购买数量设为 0,在数据库中添加触发器,当一项变为0后删除该数据:

DELIMITER $$
​
CREATE TRIGGER delete_from_cart_before_update
BEFORE UPDATE ON cart
FOR EACH ROW
BEGIN
   IF NEW.count = 0 THEN
      DELETE FROM cart WHERE uid = NEW.uid AND Did = NEW.Did;
      SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Row deleted due to count being zero.';
   END IF;
END$$
​
DELIMITER ;

当我后来用postman测试时,数据库报了这样一个错:

我才意识到这是个愚蠢想法:在update触发器中使用delete是大忌,因为delete会重新触发触发器,导致无限循环或更严重的错误。所以还是应当老老实实写delete语句。

关于同步和异步的问题:在声明周期函数中使用异步调用服务器数据是比较常见的行为,当时如果期望取到了第一个数据再请求第二个数据时,有以下两种办法:

  1. 使用await与async将生命周期内部变为同步,但是依然需要注意的是,虽然使用async将aboutToAppear变为异步,但是程序不会等待aboutToAppear内部代码执行完毕再渲染页面,因为拿到aboutToAppear的Promise是一瞬间完成的。

    async aboutToAppear() {
        await 请求1
            .then().catch()
        await 请求2
            .then().catch()
    }

  2. 在一个Promise的then中继续下一个请求,这样可以保证请求的执行是顺序的。缺点是代码较乱。

    aboutToAppear() {
        请求1
            .then(() => {
                请求2
                    .then().catch()
            }).catch()
    }

在查询订单时,需要实现的功能为根据用户编号uid查询所有订单以及订单中第一个商品的信息。使用了较为复杂的多表连结查询和分组查询,使用的sql语句如下:

select store.storeName,dish.sid,orders.state,time,dish.price,dish.dishName,img from orders
join store on orders.sid = store.id
join dish on store.id = dish.sid
join user on orders.uid = user.id
where user.id = 1 and orders.state = 0 and dish.id = (
    select min(dish.id) from dish where dish.sid = store.id
    ) group by store.id;

实际执行时产生报错:

网上的解释为

在Mysql版本为5.7.25时,在使用使用group by 时,会出现Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated...错误,这个错误的原因是 group by后面需要加上,select中的所有字段。不然就会报这个错误。

修改并规范后的sql代码

SELECT 
    store.storeName,
    store.id AS sid, -- 明确sid来源并使用AS给列一个别名以避免混淆
    orders.state,
    orders.time, -- 假设time是orders表的列
    dish.price,
    dish.dishName,
    dish.img AS img -- 假设img是store表的列,明确了来源
FROM 
    orders
JOIN 
    store ON orders.sid = store.id
JOIN 
    dish ON store.id = dish.sid AND dish.id = (
        SELECT 
            MIN(dish.id) 
        FROM 
            dish 
        WHERE 
            dish.sid = store.id
    )
JOIN 
    user ON orders.uid = user.id
WHERE 
    user.id = 1 AND orders.state = 0
GROUP BY 
    store.storeName, store.id, orders.state, orders.time, dish.price, dish.dishName, dish.img;

一个订单有可能包含多个商品,由axios将商品信息一个一个传递给服务端无疑是最低效的方法。而将所有数据一次性传递给服务器端,则需要使用post请求,将传递的商品信息放在TCP报文的数据段。这就要求了服务器需要能够处理 json 数据并具备一次性插入多条数据至数据库的功能。

该功能可以使用xml字符串拼接完成:

@Insert("<script> " +
            "insert into od " +
            "values " +
            "<foreach collection=\"items\" index=\"index\" item=\"item\" separator=\",\"> " +
            "(#{item.Oid},#{item.Did},#{item.count})" +
            "</foreach> " +
            "</script>")
    public int insertOD(@Param("items") List<Od> items);

  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,我无法直接提供完整的JavaScript期末项目的源码。但是,我可以为您提供一些关于JavaScript期末项目的一般介绍和示例。 JavaScript期末项目通常要求学生设计和开发一个具有交互性和动态功能的网页。这些项目可以涉及使用HTML、CSS和JavaScript来创建各种功能,例如表单验证、动画效果、数据展示等。 以下是一个简单的JavaScript期末项目示例,用于创建一个基本的网页表单验证功能: ```html <!DOCTYPE html> <html> <head> <title>表单验证</title> <script> function validateForm() { var name = document.forms["myForm"]["name"].value; var email = document.forms["myForm"]["email"].value; if (name == "") { alert("请输入姓名"); return false; } if (email == "") { alert("请输入电子邮件"); return false; } } </script> </head> <body> <h1>表单验证</h1> <form name="myForm" onsubmit="return validateForm()"> <label for="name">姓名:</label> <input type="text" id="name" name="name"><br><br> <label for="email">电子邮件:</label> <input type="email" id="email" name="email"><br><br> <input type="submit" value="提交"> </form> </body> </html> ``` 在这个示例中,我们创建了一个简单的表单,要求用户输入姓名和电子邮件。然后,使用JavaScript编写了一个函数`validateForm()`来验证表单数据。如果姓名或电子邮件为空,将弹出警告框并阻止表单提交。 这只是一个简单的示例,JavaScript期末项目可以更加复杂和有创意。您可以根据自己的兴趣和要求来设计和开发一个独特的项目

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值