我看NUXT3有提供传递cookie信息的方法:useRequestHeaders,但是只能拿到一个empty对象
官网链接:https://nuxt.com/docs/api/composables/use-request-headers
经过改造,如下plugins/init.server.js:
import { defineNuxtPlugin } from '#app';
function cookieFromRequestHeaders (key) {
const headers = useRequestHeaders(['cookie']);
if ('cookie' in headers) {
const cookie = headers.cookie.split(';').find(
c => c.trim().startsWith(`${key}=`)
);
if (cookie) {
return cookie.split('=')[1];
}
}
return '';
}
export default defineNuxtPlugin(async (nuxtApp) => {
const userinfo = cookieFromRequestHeaders('userinfo');
console.log(userinfo) // 运行以后 是可以拿到userinfo信息的
});
但是我的 需求是,在发送请求的时候,同时传递cookie,以及自定义header头信息,最后测试发现可以通过:{'X-Requested-With': 'XMLHttpRequest', 'cookie':headers.cookie} 实现
getUserLearnProgress: async function () {
const headers = useRequestHeaders(['cookie']);//这个 不能写到 import 同级别,只能放到生命周期函数里,否则会报错:500 nuxt instance unavailable at Module.useRequestHeaders (./node_modules/nuxt/dist/app/composables/ssr.mjs:7:41)
if (utils.isLogin()) {
let userInfo = utils.getUserInfo()
const {data, error} = await useFetch('/api/user/course', {
method: 'post',
body: {userId: userInfo.id, courseId: this.$route.query.id},
headers: {'X-Requested-With': 'XMLHttpRequest', 'cookie':headers.cookie},
})
if (error._value) {
this.$toast.error(error._value.data.msg)
} else {
if (data._value.code === 0) {
this.progress = data._value.data.progress
} else {
this.$toast.error(data._value.msg)
}
}
} else {
this.$toast.info('Please login')
}
},
到此,NUXT3 SSR渲染 获取cookie 以及自定义header头信息的问题解决了
下面这个方法是我通过 setTimeout 延迟200ms 调用也是可以解决SSR 渲染拿不到cookie的问题,但事实这个方法有二个问题 就是 这个200ms的选择问题,所以还是推荐上面的方法吧,不容易,搞了好久
setTimeout(function (){
this.getUserLearnProgress()
}.bind(this), 200)
最近在重构之前做的项目,我发现了一个新的方案:
//在 useFetch()调用之前,先调用 nextTick() 也可以不用传递cookie就可以调用
//我认为这个和上面的setTimeOut有异曲同工共的作用
await nextTick()
//执行顺序:同步代码 > nextTick > Promise> setTimeout
//执行顺序:微任务 > 宏任务
//常见的宏任务有:script setTimeout / setInterval
//常见的微任务有:Promise process.nextTick
//一般的promise对象
let promise = new Promise(function (resolve, reject) {
if (/* 异步操作成功 */) {
resolve(data);
} else {
/* 异步操作失败 */
reject(error);
}
});
//类似构建对象,使用new来构建一个Promise。Promise接受一个「函数」作为参数,该函数的两个参数分别是resolve和reject。这两个函数就是就是「回调函数」,由JavaScript引擎提供。
//Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数。
//promise.then(onFulfilled, onRejected);
promise.then(function(data) {
// do something when success
}, function(error) {
// do something when failure
});
//.catch(),该方法是.then(undefined, onRejected)的别名,用于指定发生错误时的回调函数。
promise.then(function(data) {//注意这个then只有一个回调,那么异常会走到catch那里,如果then有两个回调(如上面的代码),那么异常会被第二个回调捕获,不会被catch
console.log('success');
}).catch(function(error) {
console.log('error', error);
});
/*******等同于*******/
promise.then(function(data) {
console.log('success');
}).then(undefined, function(error) {
console.log('error', error);
});
//任务执行比较
new Promise((resolve) => {
console.log(1);//该区域并非回调函数,而是同步代码!
process.nextTick(() => {
console.log(2);
});
resolve();
process.nextTick(() => {
console.log(3);
});
console.log(4);//该区域并非回调函数,而是同步代码!
}).then(() => {
console.log(5);
});
setTimeout(() => {
console.log(6);
}, 0);
console.log(7);
// 输出顺序
1
4
7
2
3
5
6
关于nuxt3获取数据的几种方式比较:
https://nuxt.com/docs/getting-started/data-fetching
https://nuxt.com/docs/api/utils/dollarfetch
关于需要手动传递cookie的原因:
https://nuxt.com/docs/getting-started/data-fetching#passing-headers-and-cookies
原文这样说:
When we call $fetch in the browser, user headers like cookie will be directly sent to the API. But during server-side-rendering, since the $fetch request takes place 'internally' within the server, it doesn't include the user's browser cookies, nor does it pass on cookies from the fetch response.
关于在nuxt3使用$fetch的时候,会请求两次接口的问题:
在 Nuxt.js 中,如果页面在服务端和客户端都渲染,最终以客户端渲染的数据为准。这是因为客户端渲染会覆盖服务端渲染的内容。当页面在服务端渲染时,Nuxt.js 会将服务端渲染的结果作为 HTML 直接返回给浏览器,然后在浏览器端继续执行客户端渲染。在客户端渲染完成后,浏览器会用客户端渲染的内容替换服务端渲染的内容。
这样做的目的是为了提高页面加载速度和用户体验。服务端渲染可以加速首次加载,而客户端渲染可以提供更好的交互体验。在客户端渲染过程中,由于执行环境发生了变化,可能会触发一些生命周期函数(如 mounted)和数据获取方法(如 $fetch)的再次调用。
具体使用代码:
