【Node.JS】koa

文章目录

  • 概述
  • koa和express对比
  • koa下载安装
  • 使用
    • 1.创建koa项目文件目录
    • 2. 创建koa服务
    • 3. 添加路由 koa-router
    • 4. 数据库服务 mongodb
    • 5. 添加请求参数json处理 koa-bodyparser
    • 6. 用户接口举例
    • 7.引入koa一些常用插件
    • 8.用户登录验证 koa-jwt
    • 9.webpack生产打包
  • 来源

概述

Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。

koa和express对比

  • Koa采用洋葱模型

通常都会说Koa是洋葱模型,这重点在于中间件的设计。但是按照上面的分析,会发现Express也是类似的,不同的是Express中间件机制使用了Callback 实现,这样如果出现异步则可能会使你在执行顺序上感到困惑,因此如果我们想做接口耗时统计、错误处理Koa的这种中间件模式处理起来更方便些。最后一点响应机制也很重要,
Koa不是立即响应,是整个中间件处理完成在最外层进行了响应,而Express则是立即响应。

  • Koa更轻量

koa不提供内置的中间件;
koa不提供路由,而是把路由这个库分离出来了(koa/router)

  • Context对象

koa增加了一个Context的对象,作为这次请求的上下文对象(在koa2中作为中间件的第一个参数传入)。同时Context上也挂载了Request和Response两个对象。Express类似, 这两个对象都提供了大量的便捷方法辅助开发这样的话对于在保存一些公有的参 数的话变得更加合情合理。

  • 异步流程控制

express采用callback来处理异步,koa采用async/await。
async/await使用同步的写法来处理异步,明显好于callback和promise,

  • 中间件模型

express基于connect中间件,线性模型;
koa中间件采用洋葱模型(对于每个中间件,在完成了-些事情后,可以非常优雅的将控制权传递给下一个中间件,并能够等待它完成,当后续的中间件完成处理后,控制权又回到了自己)
在这里插入图片描述
同步代码
同步方法没有什么区别:

  • 01-express-同步.js
const express = require("express")
const app = express()app.use((req, res, next) => {console.log("111111")next()console.log("333333")res.send("hello world")
})app.use((req, res, next) => {// 同步操作console.log("22222")
})app.listen(3000)

运行输出

111111
22222
333333
  • 01-koa-同步 .js
const Koa = require("koa")
const app = new Koa()app.use((ctx, next) => {console.log("111111")next()console.log("333333")ctx.body("hello world")
})app.use((ctx, next) => {// 同步操作console.log("22222")
})app.listen(3000)

运行输出:

111111
22222
333333

异步代码
next()表示可以执行下一个中间件,当下一个中间件执行完成之后,如果上一个中间件没有执行完,再返回上一个中间件继续执行。

  • 01-express-异步.js
const express = require("express")
const app = express()app.use(async (req, res, next) => {console.log("111111")await next()console.log("444444")res.send("hello world")
})app.use(async (req, res, next) => {console.log("22222")// 异步操作await delay(1000)console.log("33333")
})function delay(time) {return new Promise((resolve, reject) => {setTimeout(resolve,time)})
}app.listen(3000)

运行输出:

111111
22222
444444
33333

由于next()返回的不是promise对象因此await不起作用,所以输出不会像我们所想输出

  • 01-koa-异步.js
const Koa = require("koa")
const app = new Koa()app.use((ctx, next) => {console.log("111111")next()console.log("444444")
})app.use((ctx, next) => {console.log("22222")// 异步操作delay(1000)console.log("33333")
})function delay(time) {return new Promise((resolve, reject) => {setTimeout(resolve,time)})
}
app.listen(3000)

运行输出:

111111
22222
33333
444444

koa洋葱模型,正常执行。

koa下载安装

npm init
npm i koa

Koa基本框架

const Koa = require("koa")const app = new Koa()// ctx=context 相当于res和req的合并
app.use((ctx, next) => {})app.listen(3000)

使用

1.创建koa项目文件目录

我们学习的第一步就是先搭好项目目录,这里会有我们项目中使用到的任何东西。

// 创建项目文件夹  也可手动创建
mkdir  koa-app// 进入项目文件
cd  koa-app// 添加koa依赖    
// 根据自己的包管理器执行自己的命令 我这里以yarn举例
yarn add koa -S// 新建入口文件
echo >index.js// 创建变量管理目录   constmkdir const// 创建数据库管理目录   databasemkdir database// 创建中间件管理目录   middlewaresmkdir middlewares// 创建路由管理目录   routermkdir router// 创建静态资源管理目录   staticmkdir static// 创建工具类管理目录   utilsmkdir utils// 创建html文件管理目录   view
// 主要用于测试自己接口
mkdir const// 创建webpack打包文件echo >webpack.config.js

这时候我们生成的目录结构大致如下

--koa-app--const--database--middlewares--router--static--utils--view-- index.js-- packjson.js-- webpack.config.js

2. 创建koa服务

这时候我们就可以创建koa服务,启动后就可以访问服务器目录了。

// index.jsconst Koa = require("koa");const app = new Koa();app.use(async ctx => {ctx.body = "hellO  欢迎使用koa"
})app.listen(3000);// 启动koa服务node  index.js// 访问服务在浏览器地址栏输入  localhost:3000

启动服务后我们打开浏览器就能看到"hellO 欢迎使用koa"说明我们koa程序运行成功。

3. 添加路由 koa-router

我们后台服务已经搭建好了,那下一步必不可少的就是路由管理了,这里我们使用koa-router插件

//  /router/index.js// 引入koa-router
const  Router = require('koa-router');
// 引入user路由对象
const user = require('./user/index.js');
const view = require('./view/index.js')
const goods = require('./goods/index.js');
const category = require('./category/index.js');
const upload = require('./upload/index.js')
const rule = require('./rule/index.js')
const menu = require('./menu/index.js')
const role = require('./role/index.js')
const managerUser = require('./managerUser/index.js')
const attribute = require('./attribute/index.js')// 生成新的router对象
let router = new Router();// 添加路由管理
router.use('/api/user', user.routes())
router.use('/view', view.routes())
router.use('/api/goods', goods.routes())
router.use('/api/category', category.routes())
router.use('/api/upload', upload.routes())
router.use('/api/rule', rule.routes())
router.use('/api/menu', menu.routes())
router.use('/api/role', role.routes())
router.use('/api/managerUser', managerUser.routes())
router.use('/api/attribute', attribute.routes())// 导出路由
module.exports = router

这里我是以自己写好的项目文件直接复制了,如果是测试的话不需要导入那么多路由对象,导入一个自己已经写好的就行了。

接下来我们就需要修改index.js文件与编写user路由

// /router/user/index.jsrouter.get('/list', async (ctx) => {ctx.body =  {code: 200,message: '访问成功'}
})// index.jsconst Koa = require("koa");
const router = require("./router/index.js"); // 路由
const app = new Koa();// 添加路由中间件
app.use(router.routes()).use(router.allowedMethods());
app.use(async ctx => {ctx.body = "hellO  欢迎使用koa"
})app.listen(3000);

这时候我们重新启动koa服务后,访问localhost/3000/api/user/list 就能获取ctx.body的内容了。 做到这里我们已经实现了自己的第一个接口了。剩下就是去数据库里面获取数据就形成了后台数据服务了。 是不是很棒呢!

4. 数据库服务 mongodb

这里因为学习的是mongodb数据库,所以例子都会是以mongodb数据库为例。其实用mysql的同学也可以自己去看一下mysql的引。

数据库的引入主要是做了2个步骤, 第一连接数据库,第二创建数据model对象,并执行数据库操作。 mongodb使用的是mdb语句去做的查询,mysql则是使用的sql语句。

当然每个数据库特性都不一样,在什么项目中使用什么数据库都需要在搭建项目目录的时候考虑到的,比如mysql, oracle 都是关系型的,在做一些数据关联性强的一些网站上更加适用比如电商,金融,证券,医疗等。 而非关系型的mongodb数据因为数据结构更加多变,适用与一些日记管理,博客,官网等

话不多说,我们来创建我们的数据库服务吧

添加依赖

// 添加依赖
yarn add glob mongoose  -S

创建mongosse文件

// 添加mongoose文件   /database/index.js
// 添加mongosse
const mongoose = require('mongoose')
// 数据库访问地址
const db = "mongodb://127.0.0.1/waimai"
// glob :提供匹配文件路径的方法,可以快速地找 到需要读取的文件
const glob  = require('glob');
const { resolve } = require('path')// 初始化文档模式
exports.initSchemas = async () => {await  glob.sync(resolve(__dirname, './schema', './*.js')).forEach((v) => {require(v)})
}exports.connect = () => {// 连接数据库mongoose.connect(db)return new Promise((resolve, reject) => {// 添加数据库断开监听事件mongoose.connection.on('disconnected', () => {console.log('数据库断开---------------')mongoose.connect(db)})// 添加数据库启动监听事件mongoose.connection.on('open', () => {console.log('数据库连接---------------1')mongoose.connect(db)resolve();})})
}// index.js   引入mongoose文件// moogose初始化
const { connect, initSchemas } = require("./database/index");(async () => {await connect();await initSchemas();
})();

我们重启服务后就能连接到mongodb数据库了, 在conosle里面我们能看到 数据库连接字样

5. 添加请求参数json处理 koa-bodyparser

添加新依赖

yarn add koa-bodyparser -D

更新index.js

const bodyParser = require("koa-bodyparser"); // requeast请求app.use(bodyParser());

6. 用户接口举例

添加新依赖

yarn add bcrypt -D

创建mongoose.model模型

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let ObjectId = Schema.Types.ObjectId;
// const bcrypt = require('bcrypt');const SALT_WORK_FACTOR = 10;// 前台用户表接口
const userSchema = new Schema({UserId: ObjectId,userName: {unique: true,type: String},passWord: String,avator: String,hashPassword: String,nikeName: String,address: String,isBlack: Boolean,sex: String,createAt: {type: Date,default: Date.now(),},lastLoginAt: {type: Date,default: Date.now(),},
})// 每次存储时都要执行,加盐加密
userSchema.pre('save', function (next){bcrypt.genSalt(SALT_WORK_FACTOR,(err,salt)=>{if(err) return next(err)bcrypt.hash(this.passWord,salt,(err,hash)=>{if(err) return next(err)this.hashPassword = hashnext()})})
})// 添加自定义方法
userSchema.methods = {// 对比密码一致性comparePassword: (_password, hashPassword) => {return new Promise((resolve, reject) => {// 对比密码方法bcrypt.compare(_password, hashPassword, (err, isMatch) => {if(!err) resolve(isMatch);reject(err)})}) }
}
// 发布模型
module.exports = mongoose.model('User', userSchema)

添加用户接口

const Router  = require('koa-router');
const mongoose = require('mongoose')
let router = new Router();
const User = require('../../database/schema/User')// 用户注册
router.post('/register', async (ctx) => {const userName = ctx.request.body.userName;const passWord = ctx.request.body.passWord;let newUser = new User({userName,passWord,}).save().then((res) => {ctx.body = {code: 200,message: "添加用户成功",};}).catch((err) => {ctx.body = {code: 500,message: "添加失败" + err,};});;
})router.get('/list', async (ctx) => {// 引入user模型// const User  = mongoose.model('User');const uid  = ctx.request.query.uid || '';//  分页 pagelet page = ctx.request.body.page || 1;//  分页每页数量let limit = ctx.request.body.limit || 8;// 上一次获取位置const start =(page - 1)*limit;// console.log( userName, User, 'User')const result =  await User.find().exec()console.log(result, 'result')ctx.body = {code: 200,data: result.slice((page-1)*limit, page*limit),page: {page: page,limit,total: result.length ,lastPage: parseInt(result.length / limit)}}// ctx.body = ctx.request.body;
})module.exports = router;

这时候我们就已经写好了用户添加接口与用户列表接口。因为用户的密码需要保密,我们在这里用了bcrypt去做了加盐加密,考虑到了bcrypt的加密是不可逆的所以我们这里用了passWord对原密码做了保存。

这里我们使用了schema的自定义方法与 schema的钩子函数

  • userSchema.methods

向由该 schema 编译的 model 构造的 document 添加一个实例方法.

  • userSchema.pre

给 schema 定义一个前置钩子 (pre hook)

7.引入koa一些常用插件

处理跨域问题 koa2-cors

yarn add koa2-cors -D// index,js
const koa2cors = require("koa2-cors"); // 配置跨域app.use(koa2cors({origin: "*",maxAge: 5,allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}));

添加静态文件目录 koa-static

yarn add koa-static -D// index.jsconst koaStatic = require("koa-static"); // 静态目录
app.use(koaStatic("./"));

添加websokit服务 koa-websocket

yanr add  koa-websocket -S// index.jsconst websocket = require("koa-websocket"); // socket// 这时候app需用被websoket包裹
const app = websocket(new Koa());// 建立socket连接
app.ws.use(async (ctx) => {// the websocket is added to the context as `ctx.websocket`.ctx.websocket.send("我是服务器");ctx.websocket.on("message", function (message) {// do somethingconst msg = message.toString("utf-8");console.log("客户端发来消息", msg);});
});

添加xss防御

yarn add xss -S// index.js
const xss = require('./middlewares/xss.js') // xssapp.use(xss())// /middlewares/xss.jsconst xss = require("xss"); // 需要 npm install xss -Sconst xssHandler = () => {return async (ctx, next) => {try {const body = ctx.request.body;for (const key in body) {if (typeof body[key] === "string") {body[key] = xss(body[key]);}}// 一定要添加awaitawait next();} catch (error) {// console.error(error)throw error;}};
};module.exports = xssHandler;

图片文件处理 koa-multer

yarn add koa-multer -D//  /router/upload/index.js
const Router  = require('koa-router');
let router = new Router();
const multer = require('koa-multer');//配置
const storage = multer.diskStorage({//配置图片上传的目录destination: function (req, file, cb) {console.log('destination')cb(null, 'static/images/'); //注意路径必须存在},//图片上传完成重命名filename: function (req, file, cb) {console.log('filename')// 获取后缀名var fileFormat = file.originalname.split('.');cb(null, Date.now() + '.' + fileFormat[fileFormat.length - 1]);},
});
const upload = multer({ storage: storage });
router.post('/img', upload.single('file'), async ctx => {console.log(ctx.req.file, 'ctx.req.file')ctx.body = {code: 200, data: {filename: ctx.req.file.filename,//返回文件名 path: ctx.req.file.destination + ctx.req.file.filename}} 
})module.exports = router;

请求参数验证 Joi

访问接口时会先校验参数是否传对,如果对继续后面的逻辑,如果参数校验不对则会直接返回错误信息给前端。

yarn add Joi -D// /router/user/index.jsconst Joi = require("joi");
const validateSchemaJoi = require("../../middlewares/validateSchemaJoi");
const userSchema = Joi.object({userName: Joi.string().min(1).required(),
});// 用户注册
router.post('/register', validateSchemaJoi("post", userSchema), async (ctx) => {// 注册流程
})// /middlewares/validateSchemaJoi
function validateSchemaJoi(method, schema) {async function validateSchema (ctx, next) {let data = undefined;if (method === 'get') {data = ctx.request.query;} else {data = ctx.request.body;}const { value, error } = schema.validate(data);if (error) {ctx.body = {code: 400,error};} else {next();}}return validateSchema;}module.exports =  validateSchemaJoi;

8.用户登录验证 koa-jwt

用户验证有3种方式

1。cookie 2. session 3. token

这里我们就以token来做用户验证。

添加依赖

yarn add koa-jwt jsonwebtoken -S

用户登录添加token返回

//  /router/user/index.jsvar jwt = require('jsonwebtoken');router.post('/login', async (ctx) => {const userName = ctx.request.body.userName;const passWord = ctx.request.body.passWord;// 查询用户是否存在await User.findOne({ userName: userName }).exec().then(async result => {// 如果用户名存在if(result) {let newUser = new User();// 校验用户密码await newUser.comparePassword(passWord, result.hashPassword).then(isMatch => {// 如果用户校验成功if(isMatch) {// 生成tokenconst token = jwt.sign({userName: result.userName}, 'secret', { expiresIn: '2h' });// 返回给前端ctx.body = {code: 200,message: isMatch,data: {token: token,uid: result._id}}}else {ctx.body = {code: 500,message: isMatch}}})}else {ctx.body = {code: 500,message: '用户名不存在!'}}}).catch(err => {// console.log('result----err')ctx.body = {code: 500,message: err,}})})

添加token白名单 不拦截请求

const { jwtWhiteList } = require("./const/jwtWhiteList"); // token白名单// /const/jwtWhiteList.jsconst jwtWhiteList  = [/^\/api\/user\/login/,/^\/view/,/^\/static/,"/api/managerUser/login","/api/goods/getGoodsDetailsInfo","/api/upload/img"
]
module.exports = {jwtWhiteList
}

添加路由token验证拦截

token路由拦截主要做了以下这几件事

1.koa-jwt对每个请求头部信息进行token校验,如果用户校验失败就返回401,过滤掉白名单的请求。

2.在路由中间件上面添加中间件,当用户token失效后我们就会走401步骤 返回用户token失效信息,让前端去重定向到登录页

3.用户token都是有时效性的,当然时效性越短越好,因为没用数据库去存储token所以在项目重启后可能会有失效问题,没验证过。我这默认是2小时,当小于一半的失效时间时我就会生成新的token交予前端重新生成。也就是所谓的token续存机制。

// index.jsconst jwt = require("koa-jwt"); // token验证
const jwtToken = require('jsonwebtoken');// 路由拦截器中间件
app.use(function (ctx, next) {// console.log("ce0", ctx.header.authorization)if (ctx.header && ctx.header.authorization) {const parts = ctx.header.authorization.split(" ");if (parts.length === 2) {//取出tokenconst scheme = parts[0];const token = parts[1];if (/^Bearer$/i.test(scheme)) {try {const decoded = jwtToken.verify(token, 'secret',{ complete: true });// iat: 签发时间  exp: 过期时间const { iat, exp, userName  } = decoded.payload;const nowTime = new Date().getTime()/1000;const lastTime  = (exp - nowTime)/60;// 当前事件离过期时间还剩一半的时候更新token 如果过期就走401if(decoded && 0 < lastTime &&  lastTime< ((exp-iat)/60)/2) {// console.log('更新token0')const newToken = jwtToken.sign({userName: userName}, 'secret', { expiresIn: '2h' });// console.log('更新token1', newToken)ctx.res.setHeader('Authorization', newToken)}} catch (error) {console.log("ce3")//token过期 }}}}return next().catch((err) => {if (401 == err.status || err.status === 301) {ctx.status = 401;ctx.body = {code: err.status,message: "token已经失效!!!!"};// ctx.body = {error: err.originalError ? err.originalError.message : err.message};} else {throw err;}});
});// 添加token中间件
app.use(jwt({ secret: "secret" }).unless({ path: jwtWhiteList }));

9.webpack生产打包

这里就做了简单的js打包,打包后的文件体积会变小,因为webpack设置mode为生产环境后默认就做了许多处理。

// webpack.config.js
const webpack = require("webpack");const path = require("path");const { CleanWebpackPlugin } = require("clean-webpack-plugin");const nodeExternals = require("webpack-node-externals");// const MinifyPlugin = require('babel-minify-webpack-plugin');const CopyWebpackPlugin = require('copy-webpack-plugin')module.exports = {entry: "./index.js",mode: "production",output: {path: path.resolve(__dirname, "./dist"),filename: "[name].js",},target: "node",externals: [nodeExternals()], //node 打包可去除一些警告module: {rules: [{test: /\.js$/,exclude: /node_modules/,use: [{loader: "babel-loader",options: {presets: ["@babel/preset-env"], //兼容es6,并添加.babelrc},},],},],},plugins: [// 清楚distnew CleanWebpackPlugin(),// js压缩// split切片// 复制静态目录new CopyWebpackPlugin({patterns: [{from: path.resolve(__dirname, './static'),to: path.resolve(__dirname, './dist/static')}]})// new MinifyPlugin() //压缩js],};// packjson.js  添加启动指令"build": "webpack --progress  --config webpack.config.js",
"prd_server": "node ./dist/main.js"

来源

你需要的koa入门教学
koa框架

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/780487.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

A fatal error occurred: MD5 of file does not match data in flash!问题解决

采用的芯片是ESP32-S3-WROOM&#xff0c;16MB FLASH 开发环境是Arduino&#xff0c;烧录到100%后直接报错。 以为是Arduino的问题&#xff0c;用esp-idf开发的程序&#xff0c; 烧录的过程中&#xff0c;也是直接报错如下&#xff1a; esptool.py v4.7.0 Serial port /dev/…

k8s下搭建redis集群

记录一下近期实现的在k8s上搭建redis集群的过程 1、新建存储类 主要是为了和其它服务的存储类区分一下 redis-beta-storage 2、编写configMap redis启动时从configMap中读取配置 bind&#xff1a;默认的127.0.0.1可能会导致其它ip地址无法远程访问&#xff0c;因此修改为0.0…

揭秘情绪识别:如何让AI读懂你的心声?

最近我在研究大语言模型&#xff0c;想用它来给样本打分。 起初&#xff0c;我尝试让模型用1到5分来评分&#xff0c;但它总是极端地给出最低分或最高分&#xff0c;评分缺乏中间地带。 于是我换了个方法&#xff0c;不再用数字&#xff0c;而是用描述性的词语&#xff0c;比…

农村集中式生活污水分质处理及循环利用技术指南

立项单位&#xff1a;生态环境部土壤与农业农村生态环境监管技术中心、山东文远环保科技股份有限公司、北京易境创联环保有限公司、中国环境科学研究院、广东省环境科学研究院、中铁第五勘察设计院集团有限公司、中华环保联合会水环境治理专业委员会 本文件规定了集中式村镇生活…

Discourse 最多允许有几个分类级别

和 DISCUZ 不同&#xff0c;DISCUZ 可以允许分类下面还有分类&#xff0c;再继续分类这种嵌套式分类。 Discourse 最多只允许有 2 个分类。 如果你在已有的分类下再继续分类的话&#xff0c;系统会提示错误&#xff1a; 意思就是子分类不能再分子分类。 Discourse 尽量采取了…

数据结构(六)——图

六、图 6.1 图的基本概念 图的定义 图&#xff1a;图G由顶点集V和边集E组成&#xff0c;记为G (V, E)&#xff0c;其中V(G)表示图G中顶点的有限非空集&#xff1b;E(G) 表示图G中顶点之间的关系&#xff08;边&#xff09;集合。若V {v1, v2, … , vn}&#xff0c;则用|V|…

计算机基础系列 —— 虚拟机代码翻译器(1)

“Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program.” ―Linus Torvalds 文中提到的所有实现都可以参考&#xff1a;nand2tetris_sol&#xff0c;但是最好还是自己学习课程实现一…

Linux基础 超详细!!!

一、Linux基础命令 &#xff08;一&#xff09;Linux的目录结构 1、盘符 Linux中无盘符的概念&#xff0c;只有一个根目录 “/” 也就是只有一棵树) 而windows里面有多棵树&#xff0c;每个盘符都是一棵树的根 在Linux系统中&#xff0c;路径之间的层级关系&#xff0c;使用…

Flutter 使用 AndroidStudio 给(Android 安卓)进行签名方法

一、使用 AndroidStudio 创建签名 使用 AndroidStudio 打开 Flutter项目中的 android 文件夹首次打开 AndroidStudio 会加载一会。菜单栏 &#xff1a; Build -> Generate Signed Bundle APK... 选中 APK -> Next点击Create new....下面按照需求填写即可- 文件夹选择 项…

容器二(List接口)

目录 List 特点和常用方法 List 的常用方法&#xff1a; 两个 List 之间的元素处理 List 中操作索引的常用方法 List是指“有顺序、可重复”的容器。 List接口是Collection接口的子接口&#xff0c;因此Collection 接口中的方法 List 接口都拥有&#xff1b;同时&#xff0…

论文笔记:TALK LIKE A GRAPH: ENCODING GRAPHS FORLARGE LANGUAGE MODELS

ICLR 2024&#xff0c;reviewer评分 6666 1 intro 1.1 背景 当下LLM的限制 限制1&#xff1a;对非结构化文本的依赖 ——>模型有时会错过明显的逻辑推理或产生错误的结论限制2&#xff1a;LLMs本质上受到它们训练时间的限制&#xff0c;将“最新”信息纳入到不断变化的世…

如何注册谷歌邮箱gmail

不知道大家在工作生活中有没有需要用到谷歌邮箱的地方&#xff0c;但是最近我就用到了它。因为注册ChatGPT的事&#xff0c;用了outlook&#xff0c;hotmail邮箱注册的gpt账号都被封了&#xff0c;然后通过各方面的了解&#xff0c;发现谷歌的邮箱是没有问题的&#xff0c;不会…

Portal Particle

Unity3D Portal Particle 2.2传送门粒子效果 链接&#xff1a;https://pan.baidu.com/s/1TCMXIif5d288lXHgixnDPw?pwd1234 下载&#xff1a;资源下载链接 效果图&#xff1a;

生态鱼缸智能养殖,系统架构与框图

功能&#xff1a;自动投食&#xff08;推拉式电磁铁&#xff09;&#xff0c;温度显示的改进&#xff08;传感器已经有了&#xff09;&#xff0c;控制灯光&#xff08;白天亮晚上灭&#xff09;&#xff0c;自动补养/水循环&#xff08;水氧监测太贵了&#xff0c;根据水温&am…

【前端面试3+1】05v-if和v-show的区别、v-if和v-for能同时使用吗、Vuex是什么?【合并两个有序链表】

一、v-if和v-show的区别 v-if 和 v-show 是 Vue.js 中用来控制元素显示与隐藏的指令。 1.v-if&#xff1a; v-if 是根据表达式的真假值来决定是否渲染元素。当表达式为真时&#xff0c;元素会被渲染到 DOM 中&#xff1b;当表达式为假时&#xff0c;元素不会被渲染到 DOM 中。每…

关于未来自我的发展和一些学习方法(嵌入式方向)

我是一名大二的学生&#xff0c;考研还是就业&#xff0c;到底是重视专业课还是重视数学英语&#xff0c;这些问题一直困扰了我很久&#xff0c;但如今已经有了一些浅显的认识&#xff0c;所以才会想写这样一篇文章来记录一下自己的状态和未来的规划 下面的看法都是个人的看法&…

报错:torch.distributed.elastic.multiprocessing.errors.ChildFailedError:

错误&#xff1a; torch.distributed.elastic.multiprocessing.errors.ChildFailedError: 这个主要是torch的gpu版本和cuda不适配 我的nvcc -V是11.8 torch使用的&#xff1a; pip install torch2.0.1 torchvision0.15.2 torchaudio2.0.2 --index-url https://download.pyt…

最长有效括号(C语言)

题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 这道题&#xff0c;我看了一种解法&#xff0c;觉得很好&#xff0c;来分享一下 这道题主要是 思考 当前 ) 与之匹配 ( 在哪里 &#xff0c;记录下来&#xff0c;最后比较最大值 例子&#xff1a; 第…

听了中国电信关闭Wi-Fi双频合一功能之后,到底该连接2.4GHz还是5GHz频段?

前言 前段时间沸沸扬扬的关闭双频合一建议&#xff0c;小白也尝试关闭了一下&#xff0c;网络确实是好了不少。 有小伙伴还是有点疑虑&#xff0c;中国电信说的关闭Wi-Fi双频合一功能真的有用吗&#xff1f;点击下方蓝字一探究竟&#xff01; 中国电信建议关闭路由器的双频合一…

Python-基础部署

机器没法直接读懂我们写的代码&#xff0c;需要解释解释器作为中间的翻译&#xff0c;把代码转换成字节码在执行 安装python解释器 Download Python | Python.org 安装代码编辑器 pycharm Thank you for downloading PyCharm! 创建一个项目&#xff0c;每个项目里的文件夹…