文章目录
如何保证批量请求失败,只弹出一个toast
1使用计数器:
初始化一个计数器,记录失败请求的数量。每当请求失败(完成)时,计数器加一。
在所有请求结束后检查计数器的值,如果等于请求总数,则弹出toast。
2使用标志变量:
设置一个标志变量,默认为false。当第一个请求失败时,将标志变量设置为true。
后续的请求失败后,检查这个标志变量,如果是true则不再进行设置,确保toast只弹出一次。
在所有请求结束后,检查标志变量,如果是true则弹出toast。
所有的请求都通过Promise.all
来[并行处理] ,最后检查结果数组中是否有失败的情况,并且确保只弹出一个toast。
javascript">
function batchRequest(urls) {let hasFailed = false;const promises = urls.map(url => {return request(url).catch(error => {if (!hasFailed) {hasFailed = true;}return error; // 返回错误,但不直接处理});});Promise.all(promises).then(results => {// 检查是否有失败的请求if (results.some(result => result === 'Failure')) {if (hasFailed) {showToast('所有请求均失败');}}});
}
如何减少项目里的if-else
1使用多态
将if else语句中的不同分支封装成不同的类,并定义一个共同的接口或基类,通过调用接口或基类的方法来执行相应的逻辑。这样可以将条件判断转移到对象的创建阶段,减少代码中的条件判断语句。
2使用策略模式
将if else语句中的不同分支封装成不同的策略类,每个策略类实现一种特定的逻辑。通过将策略类作为参数传递给一个统一的执行方法,根据不同的情况选择相应的策略类执行逻辑。这样可以将条件判断转移到方法的调用阶段,减少代码中的条件判断语句。
3使用字典映射
将if else语句中的不同分支作为字典的键值对,根据条件选择相应的键,然后通过字典获取对应的值执行相应的逻辑。这样可以将条件判断转移到字典的查找过程,减少代码中的条件判断语句。
4使用状态模式
将if else语句中的不同分支封装成不同的状态类,每个状态类表示一种特定的状态,并定义相应的方法。通过将状态类作为属性保存在一个上下文对象中,根据不同的情况切换状态,并调用相应状态类的方法执行逻辑。这样可以将条件判断转移到状态的切换过程,减少代码中的条件判断语句。
babel-runtime 作用是啥
babel-runtime
的主要作用就是**将在使用 babel
进行代码转换时可能被重用的代码抽取成单独的模块,以避免在每个文件中重复出现相同的代码。**它通过模块导入的方式引入这些功能,从而避免了对全局作用域的修改或污染。
使用 babel-runtime
通常需要配合 babel-plugin-transform-runtime
插件一起使用。babel-plugin-transform-runtime
插件会进行一些处理,例如自动导入 babel-runtime/core-js
,并将全局静态方法、全局内置对象映射到对应的模块;将内联的工具函数移除,改成通过 babel-runtime/helpers
模块进行导入;如果使用了 async/generator
函数,则自动导入 babel-runtime/regenerator
模块等。
这样,在代码中如果需要使用特定的功能,只需从 babel-runtime
相应的模块中导入即可,而不是直接使用全局的对象或函数。
如何实现 PDF 预览和下载
1浏览器内置PDF阅读器
浏览器内置PDF阅读器 是实现PDF文件预览的最直接方式。用户只需在HTML中插入<embed>
或<iframe>
标签,并设定其src
属性为PDF文件的URL即可。
<embed src="path/to/your-document.pdf" type="application/pdf" width="100%" height="600px">
<iframe src="path/to/your-document.pdf" width="100%" height="600px"></iframe>
浏览器会自动调用内置的PDF阅读器插件来显示PDF内容,实现预览效果。这种方法的优点是简单快捷、不依赖外部库,但可能在PDF文件较复杂或需要额外交互时遇到限制
js_82">2使用PDF.js库
使用JavaScript库PDF.js 是另外一种流行的方式,它是一个通用的、兼容各主流浏览器的PDF阅读器。PDF.js使用HTML5的Canvas API对PDF文件进行渲染,使其能在不支持插件的情况下工作。
要使用PDF.js,你需要首先引入该库:
<script src="https://mozilla.github.io/pdf.js/build/pdf.js"></script>
随后,你可以通过JavaScript代码加载PDF文件,并在指定的Canvas上渲染出来:
javascript">pdfjsLib.getDocument('path/to/your-document.pdf').promise.then(function(pdfDoc) {pdfDoc.getPage(1).then(function(page) {var canvas = document.getElementById('pdf-canvas');var context = canvas.getContext('2d');var viewport = page.getViewport({scale: 1});canvas.height = viewport.height;canvas.width = viewport.width;var renderContext = {canvasContext: context,viewport: viewport};page.render(renderContext);});
});
3后端服务生成图像预览
在一些情况下,前端直接处理PDF文件可能不是最佳选择,尤其是涉及到安全性或者性能时。这时你可以选择后端服务生成图像预览
后端服务可以用第三方库,如Python的PyMuPDF或Java的Apache PDFBox,来处理PDF文件,将其转换成图片并发送到前端
这种方法的优点是前端不需要处理复杂的文件渲染,降低了前端的计算和渲染压力。不过,这也意味着增加了后端的处理负载,并需要处理前后端之间的文件传输。
前端请求中断的方式和原理
1 Axios.CancelToken
axios
对象有一个属性叫CancelToken
,该属性提供了中断已经发出去的请求的方式。具体使用方式有两种:
方式一:执行器模式
javascript">const CancelTokenFunc = axios.CancelToken;
let cancel;
// 发送请求
axios.get("https://jsonplaceholder.typicode.com/todos/1", {cancelToken: new CancelTokenFunc(function executor(c) {// 将 cancel 函数赋值给外部变量cancel = c;}),
}).catch((error) => {console.log(error.message);});
// 取消请求
setTimeout(() => {cancel("Operation canceled by the user.");}, 1000);
先获取一个中断构造函数CancelTokenFunc
,用这个构造函数new
出一个实例赋值给get
请求的参数cancelToken
字段。
在调用CancelTokenFunc
构造函数new
出一个实例的时候,我们传入了一个执行器函数,该执行器会接受一个参数,这个参数就是用来控制中断请求的取消函数,接着我们把该参数函数赋值给外部变量,这样就可以在外部需要的时候执行中断请求的操作。
方式二:令牌模式
js">// 创建一个 CancelToken 源
const CancelTokenFunc = axios.CancelToken;
const { token, cancel } = CancelTokenFunc.source();
// 发送请求
axios.get("https://jsonplaceholder.typicode.com/todos/1", {cancelToken: token,}).catch((error) => {console.log(error.message);});
// 取消请求
setTimeout(() => {cancel("Operation canceled by the user.")}, 1000);
用CancelTokenFunc
的source
方法生成一个取消令牌源,并从取消令牌源中解构出token
和cancel
字段,然后在GET
请求中将取消令牌源的token
传递给cancelToken
,接着在外部调用请求令牌源的cancel
方法来取消请求。
2 AbortController
AbortController
是一个Web API,用于控制和管理可中止的异步操作,例如 fetch
请求、DOM
操作。接下来我们看看怎么用AbortController
来中止请求。
javascript">// 创建一个 AbortController 信号源
const controller = new AbortController();
const { signal } = controller;// 发送请求
fetch("https://jsonplaceholder.typicode.com/todos/1", {signal,
}).catch((error) => {console.log(error);
});
// 取消请求
setTimeout(() => {controller.abort("Operation canceled by the user.");
}, 1000);
创建一个AbortController
信号源,在fetch
请求的时候传递一个信号给请求的signal
参数,之后便可以在请求的外部通过调用信号源的abort
方法来取消请求。
令牌中断请求原理
将token
声明为对象,并在第5行中给token
添加一个promise
属性,该属性是一个Promise
实例,并且将Promise
实例的resolve
方法传递给了cancel
变量,这样,当调用执行cancel()
的时候,就是在执行resolve()
,token
的promise
属性就能触发then
回调函数。
cancelToken
需要携带一个回调属性,在外界执行cancel
方法时触发回调。
给cancelToken
挂载一个Promise
实例的属性,然后将这个Promise
属性的resolved
方法传递给cancel
,当执行cancel
函数的时候,其实就是执行resolve()
,从而改变Promise
实例的状态,我们就能在Promise
实例的then
方法中执行需要的操作。
javascript">function fetchData(url, options = {}) {const { cancelToken } = options;return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.open('GET', url);// 监听请求状态变化,处理请求的常规逻辑// 其他代码// 监听取消请求if (cancelToken) { // 需要在外界调用cancel请求的时候,调用xhr.abort()方法中止请求 // 并调用reject函数将Promise对象的状态改成rejected cancelToken.promise.then((msg) => { xhr.abort(); reject(new Error(msg)); }) }xhr.send();});
}
将token
声明为对象,并给token
添加一个promise
属性,该属性是一个Promise
实例,并且将Promise
实例的resolve
方法传递给了cancel
变量,当调用执行cancel()
的时候,就是在执行resolve()
,token
的promise
属性就能触发then
回调函数.
javascript">function CancelToken() {}
CancelToken.source = function () {let cancel;const token = {promise: new Promise((resolve) => {cancel = resolve})};return {cancel,token,};
};
执行器模式原理
- 在
this
上挂载了promise
属性,该属性是一个Promise对象,同时,为了达到在外部触发该Promise对象的状态变更,我们将其resolve
方法保存给了外部变量resolvePromise
。 - 声明构造函数的时候声明了
executor
入参。 - 在执行器调用的时候传入一个函数作为入参,同时在函数内部执行
resolvePromise()
触发this.promise
状态变更。
javascript">function CancelToken(executor) {let resolvePromise;this.promise = new Promise((resolve) => { resolvePromise = resolve;});executor(function c() {resolvePromise();})
}