前端打工人必学-3分钟搞定async await Sleep等待效果(附避坑指南)
说实话,sleep这套组合拳,是我从前端小白进阶到能独立负责项目的关键转折点之一。以前看到异步操作就头疼,现在反而觉得同步代码写起来更别扭。不要为了用而用。如果一个操作本身就是同步的,别强行包成async。代码是写给人看的,过度设计比不设计还可怕。错误处理要到位。await让异步代码看起来像同步的,但错误处理不能省略。每个await后面都可能抛出错误,想清楚怎么兜底。性能意识要有。循环里无脑awa

@[toc]( 前端打工人必学-3分钟搞定async await Sleep等待效果(附避坑指南))
前端打工人必学-3分钟搞定async await Sleep等待效果(附避坑指南)
开场白:这玩意儿真能让我少加班?
说实话,我刚开始写前端那会儿,最怕的就是处理"等一等"这个需求。你说让程序睡一会儿?JavaScript直接给你个白眼——老子是单线程的,你让我睡,整个页面都给你卡死信不信?
但需求不会因为你不会就消失。老板说要轮询接口,产品经理说要动画延迟,测试妹子说按钮连点会崩… 我试过用setTimeout嵌套地狱,试过用setInterval手动计数,代码写得像意大利面条,自己看了都想吐。
直到某天深夜,我在Stack Overflow上看到一个答案,突然开窍了。原来async/await配合Promise能玩出这种花样?代码瞬间从"城中村自建房"升级成"精装公寓"。今天就把这套组合拳毫无保留地分享出来,保证你看完就能上手,下次遇到等待需求不再抓瞎。
先说个扎心真相:JavaScript压根没有真正的sleep函数
很多新手(包括当年的我)第一次搜"JS sleep"的时候,估计都看到过这种"野生教程":
// 千万别这么写!这是错误的示范!
function badSleep(seconds) {
const start = Date.now();
while (Date.now() - start < seconds * 1000) {
// 空循环,卡住主线程
}
}
兄弟,你要是敢在项目中写这玩意儿,浏览器直接表演一个页面无响应。用户疯狂点关闭按钮,CPU风扇转得像直升机,测试妹子提着刀就过来了。
JavaScript的设计哲学就是非阻塞,它从来没有C语言那种sleep(3)的函数。这不是缺陷,是特性。但问题是我们确实需要"等一等"的场景啊,怎么办?
答案就是假装睡觉——让出主线程,定个闹钟,时间到了再回来继续。听起来简单,但实现方式决定了你是"优雅地等"还是"粗暴地卡"。
为啥前端也需要假装睡一会儿
可能有人觉得,sleep不是后端的事吗?前端不就是点点按钮、发发请求?太天真了。我随便举几个血淋淋的真实场景:
场景一:接口轮询的尊严
// 错误示范:疯狂请求,服务器直接拉黑你
while (true) {
const data = await fetch('/api/status');
if (data.ready) break;
// 没有sleep,CPU爆炸,服务器也爆炸
}
场景二:动画的节奏感
用户点击提交后,按钮要先转个圈,再显示成功,最后跳转。没有延迟控制,动画像抽风一样快,用户体验稀烂。
场景三:防抖节流的优雅实现
搜索框输入停止后,等个300毫秒再发请求。这300毫秒怎么等?用sleep封装比手写定时器清爽一百倍。
场景四:顺序执行的异步流程
先上传图片,等上传完再更新用户信息,最后刷新列表。不用await的话,回调嵌套三层起步,维护起来想死。
场景五:给用户一点"正在处理"的错觉
有些操作其实很快,但用户觉得快=不靠谱。故意等个500毫秒再出结果,用户反而觉得"这系统真专业"。(别笑,心理学就是这么神奇)
async和await到底是个啥关系
这俩货是绑定CP,单飞必死。我见过太多新手只写async不写await,或者反过来,然后对着报错信息怀疑人生。
async是干嘛的?
它就是给函数贴个标签,告诉JS引擎:“嘿,我这个函数里可能有异步操作,你帮我包成Promise返回。”
// 普通函数
function normal() {
return "hello";
}
// async函数
async function asyncFunc() {
return "hello"; // 实际返回 Promise.resolve("hello")
}
console.log(normal()); // "hello"
console.log(asyncFunc()); // Promise {<fulfilled>: "hello"}
看到没?哪怕你return的是普通值,async也会自动包成Promise。这就是它的本职工作。
await是干嘛的?
它是暂停键,但注意是协程级别的暂停,不是线程级别的阻塞。简单说就是:“我先去旁边歇会儿,后面的代码等我通知再执行,但主线程你们继续用,别等我。”
async function demo() {
console.log("开始");
await sleep(1000); // 这里暂停,但页面不会卡
console.log("1秒后");
}
demo();
console.log("我不用等demo");
// 输出顺序:开始 -> 我不用等demo -> 1秒后
关键点来了:await只能用在async函数内部。你如果在普通函数里写await,引擎直接报错:SyntaxError: await is only valid in async functions。
核心代码就这几行但坑不少
好了,铺垫了这么多,上正餐。实现sleep的核心代码确实简单到离谱:
/**
* 睡眠函数 - 让程序优雅地等待指定时间
* @param {number} ms - 等待时间,单位毫秒
* @returns {Promise} - 时间到了自动resolve的Promise
*/
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
就三行,没了。但别急着复制粘贴,这里面的门道多了去了。
第一坑:时间单位搞错
我见过有人这样写:
await sleep(3); // 以为是3秒,实际是3毫秒,眨眼就没了
记住,JS的世界里默认都是毫秒。要睡3秒得写sleep(3000)。如果你嫌算零麻烦,可以封装个更友好的版本:
// 更人性化的版本,支持秒和毫秒
function sleep(time, unit = 'ms') {
const ms = unit === 's' ? time * 1000 : time;
return new Promise(resolve => setTimeout(resolve, ms));
}
// 用法
await sleep(3, 's'); // 睡3秒
await sleep(500); // 睡500毫秒
第二坑:忘记处理reject
上面的sleep函数永远会resolve,不会reject。但有时候我们需要可取消的sleep,比如用户突然切换页面了,还在等的定时器就成了内存泄漏。
/**
* 可取消的sleep - 进阶版
* @param {number} ms - 等待时间
* @param {AbortSignal} signal - 用于取消的信号
*/
function cancellableSleep(ms, signal) {
return new Promise((resolve, reject) => {
const timer = setTimeout(resolve, ms);
// 如果外部传了signal,监听取消事件
if (signal) {
signal.addEventListener('abort', () => {
clearTimeout(timer);
reject(new Error('Sleep cancelled'));
});
}
});
}
// 使用示例
const controller = new AbortController();
try {
await cancellableSleep(5000, controller.signal);
console.log('睡醒了');
} catch (err) {
console.log('被叫醒了:', err.message);
}
// 3秒后取消
setTimeout(() => controller.abort(), 3000);
第三坑:循环里的await
这是性能杀手,新手最容易踩:
// 错误示范:串行执行,慢如蜗牛
async function processItems(items) {
for (const item of items) {
await sleep(100); // 每个等100ms,100个就是10秒
await process(item);
}
}
如果items有100个,这段代码要跑10秒+。但很多时候这些操作其实可以并行:
// 正确示范:并行执行,只要100ms
async function processItems(items) {
await Promise.all(
items.map(async (item) => {
await sleep(100);
return process(item);
})
);
}
第四坑:错误处理姿势不对
用await最大的好处就是可以用try-catch,但很多人写错了:
// 错误示范:catch不到reject
async function badErrorHandle() {
try {
await Promise.reject('出错了');
} catch (e) {
console.log('捕获到:', e);
}
}
// 正确示范:await后面跟的Promise reject了,会被catch捕获
async function goodErrorHandle() {
try {
const result = await fetch('/api/data');
if (!result.ok) throw new Error('HTTP错误');
return await result.json();
} catch (e) {
console.error('请求失败:', e);
// 可以在这里重试或降级
}
}
这方案到底香在哪里
香点一:代码可读性起飞
对比下回调地狱和async/await的版本:
// 回调地狱版(别这么写,会瞎)
function oldStyle() {
setTimeout(() => {
console.log('第一步');
setTimeout(() => {
console.log('第二步');
setTimeout(() => {
console.log('第三步');
}, 1000);
}, 1000);
}, 1000);
}
// async/await版(清爽)
async function newStyle() {
await sleep(1000);
console.log('第一步');
await sleep(1000);
console.log('第二步');
await sleep(1000);
console.log('第三步');
}
香点二:错误处理统一
以前用then/catch链式调用,错误处理分散在各处。现在一个try-catch包全场:
async function robustFetch() {
try {
const user = await fetchUser();
const orders = await fetchOrders(user.id);
const details = await fetchDetails(orders[0].id);
return details;
} catch (e) {
// 不管哪一步出错,都在这里处理
console.error('流程中断:', e);
return null;
}
}
香点三:调试友好
在async函数里打断点,代码是顺序执行的,调试器一步步走很直观。回调地狱里断点跳来跳去,脑子都乱了。
香点四:类型支持好
如果你用TypeScript,async函数的返回类型自动是Promise<T>,类型推断很准确:
async function typedSleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 使用时类型安全
const result: void = await typedSleep(1000);
但也不是没有槽点
槽点一:性能陷阱
前面提到的循环await只是冰山一角。更隐蔽的是不必要的async包装:
// 没必要,普通函数就行
async function add(a, b) {
return a + b; // 同步操作包成Promise,浪费
}
// 应该这样
function add(a, b) {
return a + b;
}
每个async函数调用都有Promise创建的开销,虽然现代引擎优化得很好,但高频调用还是要注意。
槽点二:调试时的"异步堆栈"
错误堆栈里可能看不到完整的调用链,因为await把调用拆成了多个事件循环周期。Chrome DevTools现在支持"Async Stack Traces"了,但老浏览器还是头疼。
槽点三:并发控制麻烦Promise.all虽然能并行,但如果有100个请求同时发,服务器直接503。需要手动控制并发数:
/**
* 控制并发数的map
* @param {Array} items - 要处理的数组
* @param {Function} fn - 异步处理函数
* @param {number} concurrency - 最大并发数
*/
async function asyncPool(items, fn, concurrency = 5) {
const ret = [];
const executing = [];
for (const item of items) {
const p = Promise.resolve().then(() => fn(item));
ret.push(p);
if (items.length >= concurrency) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= concurrency) {
await Promise.race(executing);
}
}
}
return Promise.all(ret);
}
// 使用:最多同时发5个请求
await asyncPool(urls, fetchUrl, 5);
实际项目里我是这么玩的
玩法一:接口重试机制
接口不稳定?自动重试3次,每次等的时间翻倍(指数退避):
/**
* 带重试的fetch
* @param {string} url - 请求地址
* @param {object} options - fetch选项
* @param {number} maxRetries - 最大重试次数
*/
async function fetchWithRetry(url, options = {}, maxRetries = 3) {
for (let i = 0; i <= maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) return response;
throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (i === maxRetries) throw error;
// 指数退避:第一次等1秒,第二次等2秒,第三次等4秒
const delay = Math.pow(2, i) * 1000;
console.log(`第${i + 1}次失败,${delay}ms后重试...`);
await sleep(delay);
}
}
}
// 使用
try {
const data = await fetchWithRetry('/api/unstable-endpoint');
} catch (e) {
console.error('彻底失败:', e);
}
玩法二:防止重复提交
表单提交后禁用按钮,等3秒再恢复,防止手贱用户疯狂点击:
class FormSubmitter {
constructor() {
this.isSubmitting = false;
}
async submit(formData) {
if (this.isSubmitting) {
alert('别急,正在处理...');
return;
}
this.isSubmitting = true;
const btn = document.querySelector('#submitBtn');
const originalText = btn.textContent;
try {
btn.disabled = true;
btn.textContent = '提交中...';
const result = await fetch('/api/submit', {
method: 'POST',
body: formData
});
if (!result.ok) throw new Error('提交失败');
// 成功后给个视觉反馈,等一会儿再跳转
btn.textContent = '提交成功!';
btn.classList.add('success');
await sleep(1500); // 让用户看到成功状态
window.location.href = '/success';
} catch (error) {
btn.textContent = '提交失败,请重试';
btn.classList.add('error');
await sleep(2000); // 错误状态也显示一会儿
btn.textContent = originalText;
btn.classList.remove('error');
} finally {
this.isSubmitting = false;
btn.disabled = false;
btn.classList.remove('success');
}
}
}
玩法三:轮询直到条件满足
检查文件处理状态,每2秒查一次,最多查30次(1分钟):
/**
* 轮询检查状态
* @param {string} taskId - 任务ID
* @param {number} interval - 轮询间隔(ms)
* @param {number} maxAttempts - 最大尝试次数
*/
async function pollStatus(taskId, interval = 2000, maxAttempts = 30) {
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(`/api/tasks/${taskId}`);
const { status, result } = await response.json();
if (status === 'completed') {
return result;
}
if (status === 'failed') {
throw new Error('任务执行失败');
}
// 还在处理中,等一会儿再查
console.log(`第${i + 1}次检查,状态:${status}...`);
await sleep(interval);
}
throw new Error('轮询超时');
}
// 使用
try {
const result = await pollStatus('task-123');
console.log('任务完成:', result);
} catch (e) {
console.error('轮询出错:', e);
}
玩法四:顺序动画队列
多个动画按顺序执行,中间有延迟:
class AnimationQueue {
constructor() {
this.queue = [];
this.running = false;
}
add(animationFn, delay = 0) {
this.queue.push({ fn: animationFn, delay });
if (!this.running) this.run();
return this; // 链式调用
}
async run() {
this.running = true;
while (this.queue.length > 0) {
const { fn, delay } = this.queue.shift();
if (delay > 0) {
await sleep(delay);
}
await fn(); // 等待动画完成
}
this.running = false;
}
}
// 使用:优雅的链式动画
const anim = new AnimationQueue();
anim
.add(() => moveBox('left'), 500) // 等500ms,然后左移
.add(() => rotateBox(), 300) // 等300ms,然后旋转
.add(() => fadeOutBox(), 200) // 等200ms,然后淡出
.add(() => console.log('动画完成')); // 最后回调
玩法五:批量请求限速
有1000条数据要上传,但不能一次性全发,得一批一批来:
/**
* 批量处理,控制并发和间隔
* @param {Array} items - 数据项
* @param {Function} processor - 处理函数
* @param {object} options - 配置
*/
async function batchProcess(items, processor, options = {}) {
const {
batchSize = 10, // 每批处理数量
interval = 1000, // 批次间隔
onProgress // 进度回调
} = options;
const results = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
// 处理当前批次(并行)
const batchResults = await Promise.all(
batch.map(item => processor(item))
);
results.push(...batchResults);
// 报告进度
if (onProgress) {
onProgress({
completed: Math.min(i + batchSize, items.length),
total: items.length,
percentage: Math.round((i + batchSize) / items.length * 100)
});
}
// 不是最后一批的话,等一会儿
if (i + batchSize < items.length) {
await sleep(interval);
}
}
return results;
}
// 使用示例
const data = Array.from({length: 100}, (_, i) => ({ id: i }));
await batchProcess(
data,
async (item) => {
await uploadToServer(item);
return { id: item.id, status: 'success' };
},
{
batchSize: 5,
interval: 2000,
onProgress: ({ completed, total, percentage }) => {
console.log(`进度: ${completed}/${total} (${percentage}%)`);
}
}
);
代码跑不起来先查这几个地方
第一查:await是不是写在async外面了
这是新手最高频的错误:
// 错误!顶级await在老浏览器不支持
const data = await fetch('/api/data');
// 正确:包在async函数里
async function init() {
const data = await fetch('/api/data');
}
如果你用的是ES模块(<script type="module">),现代浏览器支持顶级await,但Node.js老版本不支持。
第二查:Promise有没有resolve
sleep函数没resolve,await就永远等下去:
// 错误的sleep,永远卡住
function badSleep(ms) {
return new Promise(() => {
setTimeout(() => {
console.log('时间到了');
// 忘了调用resolve!
}, ms);
});
}
// 正确的
function goodSleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
第三查:定时器时间单位
前面说过,再强调一遍:setTimeout和sleep都是毫秒。睡5秒写sleep(5000),不是sleep(5)。
第四查:未捕获的Promise rejection
如果await的Promise reject了,但没有try-catch,控制台会报"Uncaught (in promise)",程序可能中断:
// 危险:可能抛出未捕获的错误
async function risky() {
await Promise.reject('boom'); // 这里会抛出
}
// 安全:包上try-catch
async function safe() {
try {
await Promise.reject('boom');
} catch (e) {
console.error('捕获:', e);
}
}
第五查:this指向问题
在类方法里用await,注意this别丢了:
class MyClass {
constructor() {
this.value = 42;
}
// 错误:箭头函数没问题,但普通函数要注意
async fetchData() {
setTimeout(function() {
console.log(this.value); // undefined!this丢了
}, 100);
}
// 正确:用箭头函数保留this
async fetchDataFixed() {
setTimeout(() => {
console.log(this.value); // 42
}, 100);
}
}
几个让代码更骚的操作技巧
技巧一:带超时的sleep
有时候等太久不如直接报错:
/**
* 带超时的sleep
* @param {number} ms - 等待时间
* @param {string} message - 超时提示
*/
function sleepWithTimeout(ms, message = '操作超时') {
return new Promise((resolve, reject) => {
const timer = setTimeout(resolve, ms);
// 可以结合AbortController实现外部取消
// 这里简单演示超时逻辑
});
}
// 配合Promise.race实现超时控制
async function fetchWithTimeout(url, timeout = 5000) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('请求超时')), timeout);
});
return Promise.race([
fetch(url),
timeoutPromise
]);
}
技巧二:进度条sleep
等待的时候给用户反馈,别让用户干等:
/**
* 带进度回调的sleep
* @param {number} ms - 总等待时间
* @param {Function} onProgress - 进度回调(0-100)
* @param {number} steps - 更新次数
*/
async function sleepWithProgress(ms, onProgress, steps = 10) {
const stepTime = ms / steps;
for (let i = 0; i <= steps; i++) {
onProgress(Math.round((i / steps) * 100));
if (i < steps) await sleep(stepTime);
}
}
// 使用:模拟加载进度
const progressBar = document.querySelector('.progress-bar');
await sleepWithProgress(
3000,
(percent) => {
progressBar.style.width = `${percent}%`;
progressBar.textContent = `${percent}%`;
},
20 // 更新20次,每150ms一次
);
技巧三:条件sleep
满足某个条件才继续,否则一直等(带超时):
/**
* 等待条件满足
* @param {Function} condition - 返回boolean的条件函数
* @param {number} checkInterval - 检查间隔
* @param {number} timeout - 最大等待时间
*/
async function waitFor(condition, checkInterval = 100, timeout = 10000) {
const startTime = Date.now();
while (!condition()) {
if (Date.now() - startTime > timeout) {
throw new Error('等待条件超时');
}
await sleep(checkInterval);
}
}
// 使用:等待某个元素出现
await waitFor(
() => document.querySelector('#dynamic-content') !== null,
200, // 每200ms检查一次
5000 // 最多等5秒
);
技巧四:随机sleep
模拟真实场景,避免请求太规律被识别为爬虫:
/**
* 随机时间sleep
* @param {number} min - 最小时间(ms)
* @param {number} max - 最大时间(ms)
*/
function randomSleep(min, max) {
const ms = Math.floor(Math.random() * (max - min + 1)) + min;
return sleep(ms);
}
// 使用:请求间隔1-3秒随机
for (const url of urls) {
await fetch(url);
await randomSleep(1000, 3000);
}
性能优化这块得注意
优化点一:避免串行await
能并行的别串行:
// 慢:串行执行,总时间 = a + b + c
const a = await fetchA();
const b = await fetchB();
const c = await fetchC();
// 快:并行执行,总时间 = max(a, b, c)
const [a, b, c] = await Promise.all([
fetchA(),
fetchB(),
fetchC()
]);
优化点二:控制并发数
前面提到的asyncPool自己实现麻烦?可以用p-limit库:
import pLimit from 'p-limit';
const limit = pLimit(5); // 最多5个并发
const results = await Promise.all(
urls.map(url => limit(() => fetch(url)))
);
优化点三:及时清理定时器
如果sleep被取消了,记得清理setTimeout,避免内存泄漏:
function cleanableSleep(ms) {
let timer;
const promise = new Promise(resolve => {
timer = setTimeout(resolve, ms);
});
promise.cancel = () => {
clearTimeout(timer);
};
return promise;
}
// 使用
const sleepPromise = cleanableSleep(5000);
// 3秒后取消
setTimeout(() => sleepPromise.cancel(), 3000);
try {
await sleepPromise;
} catch (e) {
// 处理取消
}
优化点四:大任务别堵主线程
如果sleep期间还要做大量计算,考虑用Web Worker:
// worker.js
self.onmessage = async function(e) {
const { duration } = e.data;
await sleep(duration);
self.postMessage('done');
};
// 主线程
const worker = new Worker('worker.js');
worker.postMessage({ duration: 5000 });
worker.onmessage = () => console.log('后台任务完成');
最后说点掏心窝子的
说实话,async/await+sleep这套组合拳,是我从前端小白进阶到能独立负责项目的关键转折点之一。以前看到异步操作就头疼,现在反而觉得同步代码写起来更别扭。
但记住几个原则:
不要为了用而用。如果一个操作本身就是同步的,别强行包成async。代码是写给人看的,过度设计比不设计还可怕。
错误处理要到位。await让异步代码看起来像同步的,但错误处理不能省略。每个await后面都可能抛出错误,想清楚怎么兜底。
性能意识要有。循环里无脑await、大量并行请求不控制并发,这些坑踩一次就知道疼了。开发环境数据量少没问题,生产环境分分钟教做人。
兼容性要考虑。虽然现在async/await支持度很好了,但老项目可能要转译。如果你在用Babel,确保配置了@babel/plugin-transform-runtime。
面试的时候,面试官特别喜欢问异步相关的问题。从"回调地狱"到"Promise",再到"async/await",能讲清楚演进过程,说明你真的有实战经验,不只是背API。
好了,这篇从原理到实战、从坑点到优化,应该覆盖了你工作中90%的sleep场景。代码片段可以直接复制到项目里用,但建议先理解原理,再根据业务调整。
有啥问题或者更好的玩法,欢迎交流。前端这条路,就是不断踩坑、填坑、再踩新坑的过程。共勉!
欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
推荐:DTcode7的博客首页。
一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟!
| 专栏系列(点击解锁) | 学习路线(点击解锁) | 知识定位 |
|---|---|---|
| 《微信小程序相关博客》 | 持续更新中~ | 结合微信官方原生框架、uniapp等小程序框架,记录请求、封装、tabbar、UI组件的学习记录和使用技巧等 |
| 《AIGC相关博客》 | 持续更新中~ | AIGC、AI生产力工具的介绍,例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结 |
| 《HTML网站开发相关》 | 《前端基础入门三大核心之html相关博客》 | 前端基础入门三大核心之html板块的内容,入坑前端或者辅助学习的必看知识 |
| 《前端基础入门三大核心之JS相关博客》 | 前端JS是JavaScript语言在网页开发中的应用,负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客,共同构建用户界面。 通过操作DOM元素、响应事件、发起网络请求等,JS使页面能够响应用户行为,实现数据动态展示和页面流畅跳转,是现代Web开发的核心 |
|
| 《前端基础入门三大核心之CSS相关博客》 | 介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法,同时收集精美的CSS效果代码,用来丰富你的web网页 | |
| 《canvas绘图相关博客》 | Canvas是HTML5中用于绘制图形的元素,通过JavaScript及其提供的绘图API,开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力,使得前端绘图技术更加丰富和多样化 | |
| 《Vue实战相关博客》 | 持续更新中~ | 详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅 |
| 《python相关博客》 | 持续更新中~ | Python,简洁易学的编程语言,强大到足以应对各种应用场景,是编程新手的理想选择,也是专业人士的得力工具 |
| 《sql数据库相关博客》 | 持续更新中~ | SQL数据库:高效管理数据的利器,学会SQL,轻松驾驭结构化数据,解锁数据分析与挖掘的无限可能 |
| 《算法系列相关博客》 | 持续更新中~ | 算法与数据结构学习总结,通过JS来编写处理复杂有趣的算法问题,提升你的技术思维 |
| 《IT信息技术相关博客》 | 持续更新中~ | 作为信息化人员所需要掌握的底层技术,涉及软件开发、网络建设、系统维护等领域的知识 |
| 《信息化人员基础技能知识相关博客》 | 无论你是开发、产品、实施、经理,只要是从事信息化相关行业的人员,都应该掌握这些信息化的基础知识,可以不精通但是一定要了解,避免日常工作中贻笑大方 | |
| 《信息化技能面试宝典相关博客》 | 涉及信息化相关工作基础知识和面试技巧,提升自我能力与面试通过率,扩展知识面 | |
| 《前端开发习惯与小技巧相关博客》 | 持续更新中~ | 罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等 |
| 《photoshop相关博客》 | 持续更新中~ | 基础的PS学习记录,含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结 |
| 日常开发&办公&生产【实用工具】分享相关博客》 | 持续更新中~ | 分享介绍各种开发中、工作中、个人生产以及学习上的工具,丰富阅历,给大家提供处理事情的更多角度,学习了解更多的便利工具,如Fiddler抓包、办公快捷键、虚拟机VMware等工具 |
吾辈才疏学浅,摹写之作,恐有瑕疵。望诸君海涵赐教。望轻喷,嘤嘤嘤
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益,纵其简陋未及渊博,亦足以略尽绵薄之力。倘若尚存阙漏,敬请不吝斧正,俾便精进!

更多推荐



所有评论(0)