JavaScript 异步编程

Cadence OrCAD常见引脚错误排查指南:从原理图到封装的完整解决方案 本文详细解析Cadence OrCAD设计中常见的引脚错误问题,提供从原理图到封装的系统化解决方案。涵盖错误诊断、元件库修复、封装管理及自动化处理技巧,帮助工程师高效解决ORCAP-36022等典型错误,确保设计流程顺畅。 阅读详情

异步的概念

异步(Asynchronous, async)是与同步(Synchronous, sync)相对的概念。

在传统的单线程编程中,程序的执行是按照控制流从前向后顺序执行的。而异步的概念则是不保证同步,即程序的执行可能不按照原有的序列依次执行。

简单来说就是:同步是按照代码顺序执行的,异步不按照代码顺序执行。

什么时候使用异步编程

因为同步是阻塞的,如果我们在执行一个耗时的操作,如请求一个数据导出接口,那我们浏览器需要等到接口数据返回才能继续向下进行,用户体验很不好。

所以通常我们会在执行耗时操作的时候,发起一个子线程,通过异步发起的执行操作,这样主线程能继续完成其他工作。

但是子线程会带来一个问题:主线程无法知道子线程是否已经执行完成了,如果后续需要处理一些事情,我们无法将它合并到主线程中去。

为了解决这个问题,JavaScript 中的异步操作函数往往通过回调函数来实现异步任务的结果处理。

JavaScript Promise

为了更优雅的书写复杂的异步任务,ECMAScript 6 提供了 Promise 这个类。

构造 Promise

new Promise(function (resolve, reject) {
    // 要做的事情...
});

这个对象看起来平平无奇,但是却能实现神奇的功能。

例如,要实现一个分三次输出字符串,第一次间隔 1 秒,第二次间隔 2 秒,第三次间隔 3 秒的功能,原先的代码:

// 函数瀑布
setTimeout(function () {
    console.log("First");
    setTimeout(function () {
        console.log("Second");
        setTimeout(function () {
            console.log("Third");
        }, 3000);
    }, 2000);
}, 1000);

使用 Promise 的实现方式:

new Promise(function (resolve, reject) {
    setTimeout(function () {
        console.log("First");
        resolve();
    }, 1000);
}).then(function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log("Second");
            resolve();
        }, 2000);
    });
}).then(function () {
    setTimeout(function () {
        console.log("Third");
    }, 3000);
});

将原本嵌套的逻辑,变成了顺序的,提高了可读性和可维护性。

Promise 构造函数

Promise 构造函数接受一个函数作为参数,该函数是同步的并且会被立即执行,称为起始函数。

起始函数包含两个参数 resolve 和 reject,分别表示 Promise 成功和失败的状态。

Promise 构造函数返回一个 Promise 对象,该对象具有以下几个方法:

  • then:用于处理 Promise 成功状态的回调函数。

  • catch:用于处理 Promise 失败状态的回调函数。

  • finally:无论 Promise 是成功还是失败,都会执行的回调函数。

注意以上三个方法的参数都需要是一个函数。

下面是一个使用 Promise 构造函数创建 Promise 对象的例子:

const promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    if (Math.random() < 0.5) {
      resolve('success');
    } else {
      reject('error');
    }
  }, 1000);
});
 
promise.then(result => {
  console.log(result);
}).catch(error => {
  console.log(error);
});

在构造函数执行时,起始函数就立即开始执行,setTimeout 函数指定 1 秒后会随机执行 resolve 或 reject 方法。

而 resolve 方法会执行 then 方法的参数,reject 方法中会执行 catch 方法的参数。

如果仅执行上半段,而不调用 then 和 catch,如果是走到 reject 的话,会报错 Uncaught (in promise) error。

then 函数支持多次调用,会按传入的顺序依次执行方法,有任何异常都会直接跳到 catch 序列

new Promise(function (resolve, reject) {
    console.log(1111);
    resolve(2222);
}).then(function (value) {
    console.log(value);
    return 3333;
}).then(function (value) {
    console.log(value);
    throw "An error";
}).catch(function (err) {
    console.log(err);
});

resolve() 中可以放置一个参数用于向下一个 then 传递一个值,then 中的函数也可以返回一个值传递给下一个 then。但是,如果 then 中返回的是一个 Promise 对象,那么下一个 then 将相当于对这个返回的 Promise 进行操作,即替换了原先的 Promise 对象。

但是请注意以下两点:

  1. resolve 和 reject 的作用域只有起始函数,不包括 then 以及其他序列;

  2. resolve 和 reject 并不能够使起始函数停止运行,别忘了 return。

Promise 函数

上面举例的函数比瀑布函数还要长,我们可以将他封装成一个方法。

这种返回值为一个 Promise 对象的函数称作 Promise 函数,它常常用于开发基于异步操作的库。

function print(delay, message) {
	return new Promise(function (resolve, reject) {
		setTimeout(function() {
			console.log(message);
			resolve();
		}, delay);
	});
}

// 实现
print(1000,'first')
  .then(function() {
	return print(2000, 'second');
  })
  .then(function() {
    print(3000, 'thrid');
  });

// 注意区别 情形一:then 方法的参数必须是一个函数
print(1000,'first')
  .then(function() {
	return print(2000, 'second');
  })
  .then(
    print(1000, 'thrid') // 这个 print 不在 function 内
  );
// 结果是 second 与 third 会同时打印出来,上述方法等价于
print(1000, 'first')
  .then(function() {
    print(2000, 'third');
  })
  .then(
    new Promise(function (resolve, reject) {
	  setTimeout(function() {
	    console.log('second');
	      resolve();
	  }, 3000);
	})
  );
// 即 then 里面的 Promise 的初始函数从整个语句声明的时候就开始执行了。

// 注意区别 情形二:第一个 then 里面的 print 没有被 return,没有返回自己的 Promise
print(1000, 'first')
  .then(function() {
    print(2000, 'second'); // 这里没有 return
	console.log('second finish');
  })
  .then(function() {
    print(3000, 'third');
  });
// 结果是 third 在第 4 秒被打印出来,而不是在第 6 秒,因为第二个 print 没有被 return,则后一个 then 还是第一个 print 创建的 Promise 的方法。
// 因为第一个 then 先执行了一个异步操作(new Promise)然后打印了 second finish,可以看到 second finish 紧随着 first 就被打印出来了,所以第一个 then 很快就结束了,第二个 then 开始执行。

常见问题

Q:什么时候适合用 Promise 而不是传统回调函数?
A:当需要连续、顺序地使用异步方法的时候,比如调用有先后逻辑关联的接口时,就适合使用 Promise。

Q:Promise 是一种将异步转换为同步的方法吗?
A:完全不是,Promise 只是一种更良好的编程风格。

Q:什么时候我们需要再写一个 then 而不是在当前的 then 接着编程?
A:当你需要再进行一次异步操作的时候,同时记得要 return 这个新的 Promise。

异步函数

异步函数(async function)是 ECMAScript 2017 标准的规范。

之前的 Promise 函数的实现可以变得更加简洁:

// 原先
print(1000, "First").then(function () {
    return print(2000, "Second");
}).then(function () {
    print(3000, "Third");
});

// 改进
async function asyncFunc() {
    await print(1000, "First");
    await print(2000, "Second");
    await print(3000, "Third");
}
asyncFunc();

异步函数 async function 可以将异步操作变得像同步一样简单。

异步函数中可以使用 await 指令,await 指令后必须跟着一个 Promise,异步函数会在这个 Promise 运行中暂停,直到其运行结束再继续运行。

异步函数实际上原理与 Promise 原生 API 的机制是一模一样的,只不过更便于程序员阅读。

异常处理机制将通过 try-catch 块实现:

async function asyncFunc() {
    try {
        await new Promise(function (resolve, reject) {
            throw "Some error"; // 或者 reject("Some error")
        });
    } catch (err) {
        console.log(err);
        // 会输出 Some error
    }
}
asyncFunc();

await 语句也可以正常返回 resolve 的值:

async function asyncFunc() {
    let value = await new Promise(
        function (resolve, reject) {
            resolve("Return value");
        }
    );
    console.log(value);
}
asyncFunc();

深入理解 Promise 对象

Promise 对象有以下两个特点

  1. 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:
  • pending:初始状态。

  • fulfilled:操作成功完成。

  • rejected:操作失败。

只有异步操作的结果,可以决定当前是哪一种状态,其他任何操作都无法更改这个状态。

  1. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。可能的状态流向:pending->fulfilled,pending->rejected,只有这两种,一旦发送就一直保持不再变化。

如果在改变发生后再对 Promise 对象添加回调函数,仍然可以立刻生效。这与 Event 的错过了就监听不到了不同。

function delay(delay, messgae) {
	return new Promise((resolve, reject) => {
		setTimeout(()=>{
			console.log('delay ' + delay + ' Promise');
			resolve(messgae);
		}, delay);
	});
}

let d1 = delay(1000, 'layback');

// 打印出 delay 1000 Promise 之后再执行
d1.then((msg) => {
	console.log(msg);
});
d1.then((msg) => {
	console.log(msg+'2');
});
// 可以发现都可以打印出结果,分别为 layback,layback2

Promise 优缺点

有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。

Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

then 的链式操作

then 方法可以接受参数,参数来源有两种:1. promise 中 resolve 方法传来的参数;2. 前一个 then 方法 return 的结果,如果前一个 then 方法返回的是 Promise 对象,则后一个 then 会到该 Promise 有了运行结果,才会进一步调用。

这种设计使得嵌套的异步操作从“横向发展”转变为“向下发展”。

catch 方法

Promise.prototype.catch 方法是 Promise.prototype.then(null, rejection) 的别名,用于指定发生错误时的回调函数。

Promise.all 方法与 Promise.race 方法

Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。新 Promise 的状态由多个 Promise 实例共同决定。

var p = Promise.all([p1,p2,p3]);
  • 当 p1、p2、p3 的状态都变成 fulfilled,p 的状态才会变成 fulfilled,此时 p1、p2、p3 的返回值组成数组,传递给 p 的回调函数。

  • 只要 p1、p2、p3 之中有一个被 rejected,p 的状态就变成 rejected,此时第一个被 reject 的实例的返回值,会传递给 p 的回调函数。

function delay(delay, messgae) {
	return new Promise((resolve, reject) => {
		setTimeout(()=>{
			console.log('delay ' + delay + ' Promise');
			if(delay != 5000) {
				resolve(messgae);
			} else {
				reject('delay too long');
			}
		}, delay);
	});
}

var pros = [{delay: 1000, msg: '1S'},{delay: 3000, msg: '3S'},{delay: 10000, msg: '10S'}].map((item)=>{ return delay(item.delay, item.msg);})
var prosErr = [{delay: 1000, msg: '1S'},{delay: 3000, msg: '3S'},{delay: 5000, msg: '5S'},{delay: 10000, msg: '10S'}].map((item)=>{ return delay(item.delay, item.msg);})


Promise.all(pros).then(function(msg) {
  console.log(msg);
}).catch(function(err){
  console.log(err);
});

从打印结果可以看出,Promise.all 成功时会等到所有的 Promise 对象都得到结果后,执行 resolve 得到全部 resolve 参数的一个数组。失败时,会在 reject 发生的时候就执行 catch,并且不会影响其他的异步操作继续进行(仍然打印出了 delay 10000 Promise(即前面说的无法取消))。

Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。但是,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的返回值。

Promise.resolve 方法与 Promise.reject 方法

如果 Promise.resolve 方法的参数,不是具有 then 方法的对象(又称 thenable 对象),则返回一个新的 Promise 对象,且它的状态为fulfilled。

var p = Promise.resolve('Hello');
 
p.then(function (s){
  console.log(s)
});
// Hello // p 的状态为 fulfilled, then方法会立刻执行。

Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。

var p = Promise.reject('出错了');
 
p.then(null, function (s){
  console.log(s)
});
// 或
p.catch((err)=>{console.log(err);})
// 出错了
Slurm集群调度策略详解(1)-主调度 Slurm调度系统中针对作业的调度主要有三种,主调度,回填调度,GANG调度,这篇文章主要针对主调度进行解析。 阅读详情

相关推荐

量子城域网建设设备系列(三):网络管理系统(NMS)

本文对量子网络中的网络管理系统进行了初步的介绍。

量子领域相关话题 2012

JavaScript 异步 实现异步的五种实现方法

JavaScript实现异步的五种实现方法 文章目录JavaScript实现异步的五种实现方法前言一、同步和异步是什么?1.同步任务:2.异步任务:二、异步方法有哪些(5种):1.webWork(创建分线程)2.promise(es6方法)3.Async await 异步的实现方法4.window.fetch() 的实现方法5.jquery中的deffered对象 的实现方法总结异步处理方法 前言 一、同步和异步是什么? 1.同步任务: js中的同步任务就是按照顺序执行(可以理解为A------&gt

weixin_46022934的博客 1万+

手把手教你用STM32的SPI驱动MCP2517FD实现CAN FD通信(附完整代码)

本文详细介绍了如何使用STM32通过SPI驱动MCP2517FD实现CAN FD通信,涵盖硬件连接、SPI驱动编写、寄存器配置及数据收发实战。提供完整代码示例和常见问题排查指南,帮助开发者快速构建高可靠性的CAN FD通信系统,适用于汽车电子和工业控制等领域。

weixin_30607029的博客 674

JavaScript中的异步编程

然后,我们使用.then()方法指定一个函数,该函数将结果数组作为参数,并使用Promise.all()方法将结果数组中的所有响应对象转换为文本。在该函数中,我们可以访问响应文本并在控制台中打印它。在上面的例子中,我们定义了一个async函数getData(),并在其中使用Promise.all()方法同时发起两个HTTP请求并等待它们完成。在上面的例子中,我们使用Promise.race()方法处理两个Promise对象,其中一个会在2秒后返回字符串'foo',另一个会在1秒后返回一个错误对象。

tyxjolin的专栏 3571

企业级AI Agent平台建设方案

本报告将深入剖析构成一个顶级AI Agent平台的各个功能层面,为构建者提供一份全面的战略蓝图。

分享AI和大数据领域的知识和研究 1582

Quartus原理图设计入门:从半加器到4位全加器的保姆级教程

本文提供Quartus原理图设计入门教程,详细讲解从半加器到4位全加器的实现过程。通过原理图输入法,逐步构建数字电路设计基础模块,涵盖环境搭建、逻辑设计、层次化实现及功能验证等关键步骤,帮助FPGA初学者快速掌握Quartus工具链和加法器设计方法。

weixin_29291185的博客 464

【JavaScript】异步加载脚本

异步加载脚本是提高Web应用性能的一种重要手段。通过了解异步加载脚本的原理、优势,并运用一些实用的技巧,我们可以更好地利用这一特性来优化页面加载速度,提升用户体验。希望通过本篇博客,你对JavaScript异步加载脚本有了更深入的了解,并能够在实际项目中巧妙地运用异步加载脚本来提高性能。

好久不见的流星 2959

NVIDIA显卡在Linux下的功率限制问题:RTX 3060 Laptop的解决方案与避坑指南

本文针对NVIDIA RTX 3060 Laptop显卡在Linux系统下遭遇功率限制的问题,提供了详细的诊断与解决方案。通过使用nvidia-smi工具监控显卡状态,并重点介绍了通过升级驱动、启用nvidia-powerd服务来激活Dynamic Boost 2.0功能,从而安全、智能地解锁额外显卡功率,有效提升性能。

weixin_29290947的博客 634

script标签的同步异步加载

script标签默认是同步加载的,也就是说,当读到script标签是引入外部js文件的,会立即停止对页面的向下解析,然后下载脚本并且执行,如果说js文件相对来说比较大,而且网速什么的又不是很好,那么用户在浏览网页的时候,会有很长一段时间的等待,用户体验很差。 当js文件里面没有对DOM进行操作或者对css进行操作的时候,我们可以将这个js文件设置成异步加载的,这样子会让用户体验更好。 那么如何设置js文件的异步加载呢? 有两种方式: <script defer> <script

xiaozhang_jiuke的博客 4225

宇树G1语音助手完整开发指南(上)——从零构建智能知识库对话系统

本文将详细介绍如何为宇树G1人形机器人开发一个,实现"唤醒 → 对话 → 查询 → 回复"的智能助手功能。

m0_47999117的博客 783

【YOLOv12多模态融合改进】| TFAM:时序融合注意力模块 | 引入通道 - 空间双分支注意力机制,解决双模态特征融合中时序关联不足的问题

TFAM模块通过时序信息驱动的注意力机制,解决了双时相特征融合中时序关联不足的问题,实现了更精准的变化区域定位和特征表示。其结构轻量、泛化性强,为变化检测任务提供了一种高效的特征融合解决方案。

Limiiiing的博客 866

js中【异步编程】超详细解读,看这一篇就够了

JavaScript是一门单线程语言,这意味着它同一时间只能执行一个任务。在现代Web开发中,异步编程变得尤为重要,因为许多任务(如网络请求、文件读取、定时器等)需要大量时间,如果使用同步编程模型,这些任务会阻塞整个线程,导致页面或程序卡顿。为了解决这个问题,JavaScript提供了异步编程模型,让程序在执行这些长时间任务时,可以继续执行其他代码。回调函数(Callback Functions)Promise。

2301_79858914的博客 2853

s8654

The official Snapdragon Ride SX 4.0 development board provides standardized hardware support for the secondary development and functional verification of the s8654 platform.

qq_39257814的博客 6826

什么是JavaScript异步编程?

在我们的工作和学习当中,到处充满了异步的身影,到底什么是异步,什 么是异步编程,为什么要用异步编程,以及经典的异步编程有哪些,在工 作中的场景又有什么,我们一点点深入的去学习。 什么是异步编程? 有必要了解一下,什么是异步编程,为什么要异步编程。 先说一个概念异步与同步。 介绍异步之前,回顾一下,所谓同步编程,就 是计算机一行一行按顺序依次执行代码,当前代码任务耗时执行会阻塞后 续代码的执行...

weixin_40851188的博客 7301

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

【JavaScript】异步编程

期待您的一键三连!欢迎指正!

Guiat的博客 2495

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

JS 异步编程六种方案

前言 我们知道Javascript语言的执行环境是"单线程"。也就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务。 这种模式虽然实现起来比较简单,执行环境相对单纯,但是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个...

浪里行舟的博客 2万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

JavaScript在Node.js中的异步编程

比如,同样的文件读取操作,用async/await可以写成:async function loadData() { try { let data = await fs.promises.readFile('data.json');比如说,读取文件后解析JSON,可以用Promise这样写:fs.promises.readFile('data.json').then(data => JSON.parse(data)).catch(error => console.error(error))。

2509_93948592的博客 396

JS (Javascript) 异步编程

如果还不清楚的,只能去搜索下js的同步(Synchronous)和异步(Asynchronous), 然后了解下先。2.在异步编程里理解上,也可以深挖一下 宏任务(macrotask)与微任务(microtask),然后理解下JS异步编程的设计模式和思想。咱们再考虑复杂一点点,如果调用第一个接口,得到结果后,需要把结果当作第二个接口的输入数据,然后以此类推,第三个,第四个,第五个......在 ES7 当中,一种更进一步的面向异步编程的方案被正式标准化——async/await 语法。

wanglei_leo的博客 221

如何在Node.js中实现异步编程

在Promise版本中,readFile返回一个Promise对象,我们可以通过.then()处理成功的结果,通过.catch()处理错误。为了解决这个问题,Node.js引入了异步编程模式,它通过回调、Promise和async/await等方式,使得程序能够在等待某个操作时继续执行其他任务。在这个例子中,readFile函数被声明为async,并且我们使用await来等待异步操作的结果。如果多个文件的读取操作是独立的,Promise.all()可以使它们并行执行,从而提升效率。5.2 避免回调地狱。

2201_75563235的博客 899

JS—异步编程:3分钟掌握异步编程

可能,CPU干了0.1秒的任务A,然后干0.2秒的任务B。再回到本篇的开头,JavaScript的异步编程,就可以理解为,单核CPU的并发,通过时间片的轮转方式去调度任务。可能,你会说1分钟都学不到东西了,更别说1秒,1毫秒了,能学什么东西?诶,这就是区别,机器能记住上一次执行的状态,下次再接着执行,不要杠,不接受反驳。以上,我说的都是单核,也就是1个CPU,现在手机,电脑都是4核,8核。,并行才能我们所理解的"并发",才是真正的并发。那么,问题就来了,这个并发,多线程是怎么实现的呢?

海晨忆的博客 1648

JS异步编程 【javascript】

JS异步编程 基础内容 异步的前身 setTimeout 与 setInterval 定时回调进行中断执行 let x = 3; setTimeout(() => { x = x + 3; console.log(x); }, 1000); 循环中断 每隔1000ms就会执行一次回调函数 setInterval(() => { x = x + 3; console.log(x); }, 1000); 异步解决方案 老的异步方案 利用setTimeout解决

高万禄的博客 973

JavaScript异步编程

JavaScript异步编程JS工作模式同步模式异步模式JS异步编程回调函数PromisePromise用法Promise使用案例Promise常见误区Promise链式调用Promise 异常处理Promise静态方法Promise并行执行Promise执行时序手写模拟PromiseGeneratorGenerator 用法Generator函数异步方案Generator异步递归调用优化Async/await语法糖 璃安猫: 观看学习视频总结的一些异步编程的相关知识点,还有许多不完善的地方,之后会逐渐补

weixin_43923712的博客 604

JS中的异步编程

这是本人对于JS中异步编程的理解,欢迎大家的交流,以及如果发现错误欢迎大家的指正,十分感激。

a3098448071的博客 1825

深入理解Async.js:JavaScript异步编程利器

Async.js是一个功能强大的JavaScript异步编程工具库,它提供了约70个实用的函数来处理各种异步操作场景。无论是简单的集合操作(如map、reduce、filter),还是复杂的异步流程控制(如parallel、series、waterfall),Async.js都能提供优雅的解决方案。 ## 核心特性 ### 1. 丰富的异步控制模式 Async.js提供了多种异步控制流程模式...

gitblog_00204的博客 553
上一篇: Vue 组件通过 props 传值不会更新
下一篇: Vue下载Url图片而非直接浏览器打开
一只小小翠
博客等级 码龄9年 154粉丝 48原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值