在做开发和调试过程中,经常需要考虑到一个请求或者图片等加载很慢时,应该怎么处理。
比如有用户反馈某些图片加载很慢,导致页面看起来不正常。那么我就应该针对图片加载慢进行一些处理,可是怎么模拟这个加载很慢的图片呢?
很多现有的接口,都无法模拟出这种有特殊延迟的情况,这里我们可以使用 http 模块来实现。
我们在第 1 个 http 服务器的基础上,进行改进。
res.end()方法会告知服务器当前次响应结束,若没有调用,则一直处于等待状态。
我们要实现一个有延迟的响应,可以使用 setTimeout 延迟调用 end()方法即可。这里先实现一个有延迟的接口。
http
.createServer((req, res) => {
const index = req.url.indexOf(‘?’);
if (index >= 0) {
const query = req.url.slice(index);
const ss = new URLSearchParams(query);
const timeout = ss.get(‘timeout’);
const type = ss.get(‘type’);
if (timeout && Number(timeout)) {
return setTimeout(() => {
if (type === ‘json’) {
res.writeHead(200, { ‘Content-Type’: ‘application/json’ });
res.end(JSON.stringify({ code: 0, msg: ‘hello world’ }));
} else if (type === ‘image’) {
// 输出本地一个图片
} else {
res.end(delay ${timeout}ms response
);
}
}, Number(timeout));
}
}
res.end(‘hello world!’);
})
.listen(port, ip);
想要延迟输出图片时,需要通过数据流的方式读取本地的图片,然后输出到前端:
const stream = fs.createReadStream(‘./img/s.jpg’);
const responseData = []; //存储文件流
if (stream) {
//判断状态
stream.on(‘data’, function (chunk) {
responseData.push(chunk);
});
stream.on(‘end’, function () {
const finalData = Buffer.concat(responseData);
// response.write();
res.writeHead(200, { ‘Content-Type’: ‘image/jpg’ });
res.end(finalData);
});
}
3. 实现接口的中转代理
我们有时会遇到需要的接口存在跨域,或者是内网接口的问题,这时我们就需要通过一个中间层,来对接口进行中转代理,才能正常地访问接口。
3.1 原生 http 模块来实现
实现接口代理时要注意亮点:
-
透传,接收到的所有数据,根据需要尽量都传给代理的接口,例如 cookie,参数等;
-
设置跨域头,为了方便前端的访问,我们需要在返回的头部加上 3 个可以跨域的字段;
跨域的方式有很多种,比如 jsonp 也是其中一种,但 cors 跨域是比较好的一种,前端可以有效地控制请求时间和取消请求。
在设置跨域头Access-Control-Allow-Origin
时,这里是不建议直接设置成*
。一方面是不安全,所有的域名都可以访问;再有就是前端不会再传送 cookie,无法进行一些登录态的校验等。
在设置Access-Control-Allow-Origin
之前,我们要先校验下 headers 中的 referer,如果为空或者不满足白名单的要求,则可以直接返回 403。
const allowList = [‘joke.qq.com’, ‘www.qq.com’];
if (!req.headers || !req.headers.referer) {
res.writeHead(403, ‘forbidden’);
res.end(‘403 forbidden’);
return;
}
const { hostname } = new URL(req.headers.referer);
if (!allowList.includes(hostname)) {
res.writeHead(403, ‘forbidden’);
res.end(‘403 forbidden’);
return;
}
满足要求之后,需要将 referer 最后的斜杠/
去掉,否则会设置不成功。完成的代码样例如下:
const http = require(‘http’);
const https = require(‘https’);
const ip = process.env.IP || ‘127.0.0.1’;
const port = process.env.PORT || 3001;
http
.createServer((req, res) => {
const allowList = [‘joke.qq.com’, ‘www.qq.com’];
if (!req.headers || !req.headers.referer || allow) {
res.writeHead(403, ‘forbidden’);
res.end(‘403 forbidden’);
return;
}
console.log(‘发起请求’, req.headers);
https
.get(‘https://www.v2ex.com/api/topics/latest.json’, (response) => {
let data = ‘’;
response.on(‘data’, (chunk) => {
data += chunk;
});
response.on(‘end’, () => {
res.setHeader(‘Access-Control-Allow-Origin’, (req.headers.referer || ‘’).replace(//$/, ‘’));
res.setHeader(‘Access-Control-Allow-Methods’, ‘GET, POST’);
res.setHeader(‘Access-Control-Allow-Headers’, ‘X-Requested-With,content-type’);
res.end(data);
});
})
.on(‘error’, (e) => {
console.error(请求遇到问题: ${e.message}
, e);
res.end(‘error’);
});
})
.listen(port, ip);
console.log(server has started at ${ip}:${port}
);
3.2 proxy 代理组件
若需要代理更多的接口,或者路径是从前端传过来的,我们自己倒是也可以实现,不过还有更方便的 proxy 代理组件了。
这里我们用 http-proxy 组件来实现:
const http = require(‘http’);
const httpProxy = require(‘http-proxy’);
const ip = process.env.IP || ‘127.0.0.1’;
const port = process.env.PORT || 3000;
const proxy = httpProxy.createProxyServer({
target: ‘https://www.v2ex.com’, // 代理的接口地址
changeOrigin: true,
});
http
.createServer((req, res) => {
// 设置跨域头
res.setHeader(‘Access-Control-Allow-Origin’, (req.headers.referer || ‘’).replace(//$/, ‘’));
res.setHeader(‘Access-Control-Allow-Methods’, ‘GET, POST’);
res.setHeader(‘Access-Control-Allow-Headers’, ‘X-Requested-With,content-type’);
// 将请求和响应的对象传给proxy
proxy.web(req, res);
})
.listen(port, ip);
然后前端直接按照路径发起请求即可:
axios(‘http://localhost:3000/api/topics/latest.json’).then(console.log).catch(console.error);
4. 模拟数据
前端在写页面逻辑时,经常要考虑到数据的各种情况,比如无数据时,长列表,各种长度的昵称等。
无论是读取配置的 json 文件,还是用代码生成的数据,都不具有随机性。
现在,我们可以利用 mockjs 来实现各种数据的模拟:
const http = require(‘http’);
const Mock = require(‘mockjs’);
const ip = process.env.IP || ‘127.0.0.1’;
const port = process.env.PORT || 3000;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
最后
分享一套阿里大牛整理的前端资料给大家,点击前端校招面试题精编解析大全即可免费下载
❤️ 谢谢支持,喜欢的话别忘了 关注、点赞哦。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-OUEw3ePT-1712294592925)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
最后
分享一套阿里大牛整理的前端资料给大家,点击前端校招面试题精编解析大全即可免费下载
❤️ 谢谢支持,喜欢的话别忘了 关注、点赞哦。