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除了能绘制基本的形状和文本,还可以实现动画、缩放、各种滤镜和像素转换等高级操作。

posted @ 2026-01-16 17:15  qiqimk  阅读(2)  评论(0)    收藏  举报