JavaScript笔记-浏览器[下]
注意:本篇学习笔记基于原网站: JavaScript教程 - 廖雪峰的官方网站
笔记仅作学习留档使用
本篇目录
Promise
async函数
Canvas(HTML5新增)
Promise
JavaScript的代码只能单线程执行,所以所有相关的网路操作和炼器时间都需要异步执行。异步执行可以用回调函数实现(AJAX就是典型的异步操作)
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status === 200) {
return success(request.responseText);
} else {
return fail(request.status);
}
}
}
↓ 更好的写法
// 先统一执行AJAX逻辑
let ajax = ajaxGet('http://...');
// 根据结果操作
ajax.ifSuccess(success)
.ifFail(fail);
这种“承诺将来会执行”的对象在JavaScript中称为Promise对象,有各种开源实现,在ES6中被统一规范,由浏览器直接支持。
在说明运行方法前,先简单介绍一下promise,它本身只有有三种状态
const promise = {
state: "pending", // 初始状态:进行中
// 要么变成:"fulfilled"(成功)
// 要么变成:"rejected"(失败)
value: null, // 成功时的值
reason: null // 失败时的原因
};
常用的方法(以点外卖举例)
| 方法 | 作用 | 比喻 |
|---|---|---|
.then() |
成功时做什么 | 外卖到了之后... |
.catch() |
失败时做什么 | 外卖出问题时... |
.分别() |
无论成功失败都做 | 最后都要收拾桌子 |
Promise.all() |
等所有都完成 | 等所有外卖都到齐 |
Promise.race() |
谁先完成用谁 | 哪个外卖先到先吃哪个 |
Promise.resolve() |
创建已成功的 Promise | 已经有现成的食物 |
Promise.reject() |
创建已失败的 Promise | 直接拒绝订单 |
以买披萨外卖举例:
// 外卖的三个状态
const pizzaPromise = new Promise((resolve, reject) => {
// 1. 初始状态:pending(订单已接收,正在制作)
console.log("商家已接单,开始制作披萨...");
setTimeout(() => {
const isSuccess = Math.random() > 0.3;
if (isSuccess) {
// 2. 成功状态:fulfilled(披萨做好了)
resolve("🍕 披萨做好了!");
} else {
// 3. 失败状态:rejected(制作失败了)
reject("🔥 烤箱坏了,披萨糊了!");
}
}, 2000);
});
// 处理结果
pizzaPromise
.then(result => {
console.log("成功:", result);
console.log("我下楼取餐");
})
.catch(error => {
console.log("失败:", error);
console.log("我重新点一家");
})
.finally(() => {
console.log("不管成功失败,我都要收拾桌子");
});
有了执行函数,我们就可以用一个Promise对象来执行它,并在将来某个时刻获得成功或失败的结果。
除去基本的异步,还有一些额外的功能:
Promise.all()- 等所有外卖都到了再开饭
// 同时点披萨、可乐、薯条
const pizza = orderPizza(); // Promise
const cola = orderCola(); // Promise
const fries = orderFries(); // Promise
// 等三个都到了
Promise.all([pizza, cola, fries])
.then(foods => {
console.log("所有外卖都到了:", foods);
// foods是数组:["🍕", "🥤", "🍟"]
console.log("可以开饭了!");
})
.catch(error => {
console.log("有一样没到,吃不了饭:", error);
});
Promise.race()- 哪个外卖先到先吃哪个
// 同时点三家店的外卖,谁先到吃谁的
const kfc = orderKFC(); // 预计30分钟
const mcd = orderMcDonalds(); // 预计20分钟
const pizzaHut = orderPizzaHut(); // 预计25分钟
Promise.race([kfc, mcd, pizzaHut])
.then(fastestFood => {
console.log(fastestFood + " 先到了!");
console.log("先吃这个垫垫肚子");
});
// 如果是麦当劳先到,就打印:"麦门先到了^^"
Promise.resolve()- 假装点了外卖
// 有时候我们已经有东西了,但还想用Promise的格式
const instantNoodle = Promise.resolve("泡面"); // 泡面已经有了
instantNoodle
.then(food => console.log("吃:" + food));
// 立即输出:"吃:泡面"```
Promise.reject()- 假装外卖"秒拒"
```const failedOrder = Promise.reject("没钱付款");
failedOrder
.catch(reason => console.log("失败原因:" + reason));
// 立即输出:"失败原因:没钱付款"
async函数
关键字 async 配合 await 调用Promise实现异步操作,可以实现同步写法类似的代码
async function get(url) {
let resp = await fetch(url);
let result = await resp.json();
return result;
}
async function可以定义一个异步函数,在函数内部,用await调用另一个异步函数,执行起来是异步的
let resp = await fetch(url);
||等价于
let promise = fetch(url);
promise.then((resp) => {
// 拿到resp
});
对于catch()功能,可以调用await直接使用try { … } catch实现。
async function get(url) {
try {
let resp = await fetch(url);
let result = await resp.json();
return result;
} catch (e) {
// 出错了
}
}
注意await调用必须在async function中,对于同步函数,需要调用async function时,不可以使用await。可以直接调用函数获得Promise对象,后面加上then()和 catch()获取结果。
Canvas(HTML5新增)
实现在不借助Flash插件的情况下用JavaScript在绘制各种图表、动画等。
一个Canvas定义了一个指定尺寸的矩形框,在这个范围内我们可以随意绘制
<canvas id="test-canvas" width="300" height="200"></canvas>
通常在 <canvas> 内部添加一些说明性HTML代码,如果浏览器不支持Canvas,它将显示 <canvas> 内部的HTML。
获取画笔
getContext('2d') 方法会拿到一个 CanvasRenderingContext2D 对象,所有的绘图操作都需要通过这个对象完成
// 获取画布元素
const canvas = document.getElementById('myCanvas');
// 2D绘图上下文用笔
const ctx = canvas.getContext('2d');
// 也有3D的,但更复杂(本节不讲这个)
const gl = canvas.getContext('webgl');
绘制图形
Canvas的坐标以左上角为原点,水平向右为X轴,垂直向下为Y轴,以像素为单位,所以每个点都是非负整数
绘制矩形
// 1. 填充矩形(实心)
ctx.fillStyle = 'red'; // 设置填充颜色
ctx.fillRect(50, 50, 200, 100); // (x, y, 宽度, 高度)
// 2. 描边矩形(空心)
ctx.strokeStyle = 'blue'; // 设置边框颜色
ctx.lineWidth = 5; // 设置边框粗细
ctx.strokeRect(100, 100, 150, 80);
// 3. 清除矩形区域
ctx.clearRect(80, 80, 100, 50); // 擦除这块区域
绘制路径(画线、形状)
// 开始一条新路径
ctx.beginPath();
// 移动到起点(不提笔移动)
ctx.moveTo(100, 100);
// 画线到某点
ctx.lineTo(200, 150);
ctx.lineTo(150, 200);
// 画圆形
ctx.arc(300, 300, 50, 0, Math.PI * 2); // (圆心x, 圆心y, 半径, 起始角度, 结束角度)
// 闭合路径(回到起点)
ctx.closePath();
// 设置样式
ctx.strokeStyle = 'green';
ctx.lineWidth = 3;
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; // 带透明度
// 绘制
ctx.stroke(); // 描边
ctx.fill(); // 填充
绘制文本
// 设置文字样式
ctx.font = 'bold 30px Arial'; // 粗细 大小 字体
ctx.fillStyle = 'black';
ctx.textAlign = 'center'; // 对齐方式:left, center, right
ctx.textBaseline = 'middle'; // 基线:top, middle, bottom
// 绘制填充文字
ctx.fillText('Hello Canvas', 400, 50);
// 绘制空心文字
ctx.strokeText('Hello Canvas', 400, 100);
Canvas除了能绘制基本的形状和文本,还可以实现动画、缩放、各种滤镜和像素转换等高级操作。
浙公网安备 33010602011771号