JS如何实现Promise调度?Promise的执行顺序

promise调度的核心在于微任务队列的高优先级,即promise的then、catch、finally回调被放入微任务队列,在当前宏任务结束后立即执行,因此比settimeout等宏任务更早执行;promise构造函数内的同步代码会立即执行,而其回调通过事件循环机制在微任务阶段处理,确保异步操作的有序性和及时性;链式调用通过.then返回新promise实现顺序执行,每个回调在前一个promise解决后被推入微任务队列;并行执行如promise.all、promise.race等则让多个promise同时开始,待条件满足后将聚合结果的回调推入微任务队列;async/await是基于promise的语法糖,await暂停函数执行并将后续逻辑作为微任务注册,恢复时继续执行,但连续await独立异步操作会导致串行化性能问题,需通过先启动所有promise再await结果来优化;顶层await仅在支持的模块环境中可用,理解其底层调度机制有助于避免陷阱并提升异步代码的可读性与效率。

JS如何实现Promise调度?Promise的执行顺序

Promise调度在JavaScript中,简单来说,就是一套关于如何以及何时执行异步操作回调的规则,它的核心在于JavaScript事件循环中“微任务队列”(Microtask Queue)的优先级机制。Promise的执行顺序,概括起来是:Promise本身(构造函数内的同步代码)会立即执行;而其

.then()

,

.catch()

,

.finally()

等回调,则会被放入微任务队列,等待当前宏任务(如主脚本执行)完成后,立即、批量地执行。这赋予了Promise回调比

setTimeout

等宏任务更高的优先级。

JS如何实现Promise调度?Promise的执行顺序

要理解Promise的调度,我们得深入到JavaScript的“心脏”——事件循环(Event Loop)。我常常觉得,这个概念是理解JS异步编程的基石,也是Promise能如此“魔幻”地处理异步的秘密。

当一个Promise被创建时,其构造函数内部的代码是同步执行的。比如:

console.log('开始');new Promise(resolve => {    console.log('Promise构造函数内部');    resolve();});console.log('结束');// 输出:// 开始// Promise构造函数内部// 结束

这很直接,对吧?但一旦涉及到

.then()

,

.catch()

,

.finally()

,事情就变得有点意思了。这些方法注册的回调函数,不会立即执行,它们会被“排队”到微任务队列里。而微任务队列的优先级非常高,它会在当前正在执行的宏任务(比如整个脚本的执行、一个

setTimeout

的回调、一个用户事件处理)结束后,但在浏览器渲染或执行下一个宏任务之前,被清空。

这就像是,你手里有一堆待办事项(宏任务),但突然来了几个“紧急”的小任务(微任务),你必须先把这些紧急的小任务处理完,才能继续你的大任务,或者开始下一个大任务。Promise的回调就是这些“紧急”的小任务。

为什么Promise回调比setTimeout更早执行?

这是个经典问题,也是理解Promise调度机制的关键点。我刚接触Promise的时候,也曾被这个“反直觉”的现象困扰过。

答案就藏在JavaScript的事件循环机制里。简单来说,事件循环不断地检查两类任务队列:宏任务队列(Macrotask Queue)和微任务队列(Microtask Queue)。

宏任务(Macrotasks):包括像

setTimeout

,

setInterval

, I/O操作(如网络请求完成),用户交互事件(点击、键盘输入),以及整个脚本的执行本身。每次事件循环迭代,只会从宏任务队列中取出一个任务来执行。微任务(Microtasks):主要包括Promise的回调(

.then()

,

.catch()

,

.finally()

),

MutationObserver

的回调,以及

queueMicrotask

等。

关键点在于:在每次宏任务执行完毕之后,事件循环会立即清空所有的微任务队列,然后再去宏任务队列中取下一个宏任务。

所以,当你写下这样的代码时:

console.log('1');setTimeout(() => {    console.log('2');}, 0);Promise.resolve().then(() => {    console.log('3');});console.log('4');

执行顺序是这样的:

console.log('1')

同步执行。

setTimeout

的回调被放入宏任务队列。

Promise.resolve().then()

的回调被放入微任务队列。

console.log('4')

同步执行。当前宏任务(主脚本)执行完毕。事件循环检查微任务队列,发现

console.log('3')

,立即执行。微任务队列清空。事件循环检查宏任务队列,发现

console.log('2')

,执行。

最终输出:

1 -> 4 -> 3 -> 2

这种优先级设计,在我看来,是Promise能够保证其回调“尽快”执行,并且在一定程度上保持异步操作“有序”的关键。它让Promise在处理异步流程控制时显得更为强大和可预测。

Promise链式调用与并行执行的调度差异

Promise在实际应用中,往往不会是孤立的一个,它更多地以链式调用或并行组合的形式出现。这两种模式在调度上,虽然都遵循微任务的规则,但在逻辑流程和性能考量上,有着明显的差异。

链式调用 (

.then().then()...

)

链式调用是Promise最常见的用法之一,它允许我们将一系列异步操作按顺序串联起来。比如:

function step1() {    console.log('Step 1 开始');    return new Promise(resolve => setTimeout(() => {        console.log('Step 1 完成');        resolve('数据A');    }, 100));}function step2(data) {    console.log('Step 2 接收到:', data);    return new Promise(resolve => setTimeout(() => {        console.log('Step 2 完成');        resolve('数据B');    }, 50));}console.log('主流程开始');step1()    .then(resultA => {        console.log('Promise链:进入第一个then');        return step2(resultA); // 返回一个新的Promise    })    .then(resultB => {        console.log('Promise链:进入第二个then,最终结果:', resultB);    })    .catch(error => {        console.error('Promise链:发生错误:', error);    });console.log('主流程结束');

在这个例子中:

step1()

被调用,其内部的

setTimeout

被放入宏任务队列。

step1()

返回的Promise对象被

.then()

监听。当

step1

内部的

setTimeout

执行完毕,

resolve('数据A')

被调用,

step1

返回的Promise状态变为fulfilled。此时,

step1().then(...)

的回调被放入微任务队列。事件循环清空微任务队列,执行第一个

.then()

的回调,其中又调用了

step2()

step2()

返回的Promise对象被后续的

.then()

监听。当

step2

内部的

setTimeout

执行完毕,

resolve('数据B')

被调用,

step2

返回的Promise状态变为fulfilled。此时,第二个

.then()

的回调被放入微任务队列。事件循环清空微任务队列,执行第二个

.then()

的回调。

链式调用的核心在于,每个

.then()

(或

.catch()

,

.finally()

)都会返回一个新的Promise,后续的

.then()

是监听这个新Promise的状态。这意味着每个步骤都是在前一个步骤完成后才开始的,保证了严格的顺序性。

并行执行 (

Promise.all()

,

Promise.race()

,

Promise.allSettled()

)

当你有多个相互独立的异步操作,并且你关心它们全部完成(或其中一个完成)的结果时,并行执行就派上用场了。这通常能显著提高效率,因为它不会等待一个操作完成后再开始下一个。

Promise.all(iterable)

: 等待所有Promise都成功(fulfilled)才成功,如果其中任何一个Promise失败(rejected),则立即失败。

Promise.race(iterable)

: 哪个Promise最先成功或失败,就以那个Promise的结果为准。

Promise.allSettled(iterable)

: 等待所有Promise都“落定”(settled,即无论是成功还是失败),然后返回一个包含每个Promise结果(状态和值)的数组。

Promise.all()

为例:

function fetchUser() {    return new Promise(resolve => setTimeout(() => {        console.log('Fetched user');        resolve({ id: 1, name: 'Alice' });    }, 200));}function fetchPosts() {    return new Promise(resolve => setTimeout(() => {        console.log('Fetched posts');        resolve([{ id: 101, title: 'Post A' }]);    }, 100));}console.log('开始并行获取数据');Promise.all([fetchUser(), fetchPosts()])    .then(results => {        console.log('所有数据获取完成:', results);    })    .catch(error => {        console.error('并行获取数据失败:', error);    });console.log('并行获取指令已发出');

这里,

fetchUser()

fetchPosts()

会几乎同时开始执行(在它们被调用的那一刻)。它们的内部

setTimeout

会各自进入宏任务队列。当它们各自的Promise被resolve后,

Promise.all()

.then()

回调才会被放入微任务队列。

调度差异总结:

链式调用:严格按序执行,前一个Promise解决后,其

.then

回调进入微任务队列,执行完毕后才可能触发下一个Promise的开始。并行执行:所有Promise几乎同时开始执行,它们各自的完成状态会独立地被

Promise.all

/

race

/

allSettled

聚合,只有当聚合条件满足时,聚合Promise的

.then

回调才会被放入微任务队列。

理解这两种模式的调度差异,对于优化异步操作的性能和逻辑流程至关重要。

async/await在Promise调度中的角色与陷阱

async/await

是ES2017引入的语法糖,它让异步代码看起来和写同步代码一样,极大地提高了代码的可读性。但需要明确的是,

async/await

并没有改变Promise的底层调度机制,它只是在Promise之上提供了一个更优雅的语法封装。

async/await

的角色:

一个

async

函数总是返回一个Promise。当你在

async

函数内部使用

await

关键字时,它会“暂停”当前

async

函数的执行,直到它等待的Promise解决(fulfilled或rejected)。一旦该Promise解决,

async

函数会从暂停的地方继续执行。

这个“暂停”和“恢复”的过程,其实就是巧妙地利用了Promise的微任务调度。当

await promise

时,如果

promise

还没有解决,那么

async

函数会把剩余的代码作为这个

promise

.then()

回调来处理,并将这个

.then()

回调放入微任务队列。

async function fetchData() {    console.log('fetchData 开始');    const user = await new Promise(resolve => setTimeout(() => {        console.log('获取用户数据完成');        resolve({ name: 'Bob' });    }, 100));    console.log('用户数据:', user);    const posts = await new Promise(resolve => setTimeout(() => {        console.log('获取文章数据完成');        resolve([{ title: 'Hello World' }]);    }, 50));    console.log('文章数据:', posts);    return { user, posts };}console.log('主脚本开始');fetchData().then(data => {    console.log('fetchData 完成并返回:', data);});console.log('主脚本结束');

执行流程大致是:

console.log('主脚本开始')

同步执行。

fetchData()

被调用,

console.log('fetchData 开始')

同步执行。遇到第一个

await

new Promise(...)

立即执行,其内部的

setTimeout

放入宏任务队列。

fetchData

函数在这里“暂停”,它把等待用户数据的剩余部分作为一个微任务,注册到当前Promise的解决回调中。

console.log('主脚本结束')

同步执行。当前宏任务(主脚本)执行完毕。事件循环清空微任务队列(目前没有Promise回调被放入)。事件循环从宏任务队列中取出第一个

setTimeout

(获取用户数据)执行。

获取用户数据完成

打印,用户数据Promise解决。

fetchData

函数注册的微任务(即

await

之后的代码)被放入微任务队列。事件循环清空微任务队列,执行

fetchData

剩余部分:

console.log('用户数据:', user)

。遇到第二个

await

new Promise(...)

立即执行,其内部的

setTimeout

放入宏任务队列。

fetchData

函数再次“暂停”,把等待文章数据的剩余部分作为一个微任务注册。事件循环从宏任务队列中取出第二个

setTimeout

(获取文章数据)执行。

获取文章数据完成

打印,文章数据Promise解决。

fetchData

函数注册的微任务(即第二个

await

之后的代码)被放入微任务队列。事件循环清空微任务队列,执行

fetchData

剩余部分:

console.log('文章数据:', posts)

,并最终返回结果。

fetchData()

返回的Promise解决,其

.then()

回调被放入微任务队列。事件循环清空微任务队列,执行

console.log('fetchData 完成并返回:', data)

常见的陷阱:

阻塞非Promise值:

await

后面跟着的如果不是Promise,它会立即解析,不会产生异步等待。但这本身不是陷阱,只是需要理解其行为。真正的陷阱是误以为

await

能让所有东西都变异步。

async function example() {    console.log('A');    await 1; // 立即解析,不等待    console.log('B');}example(); // 输出 A -> B

串行化非必要操作:

await

的默认行为是串行等待。如果你有多个独立的异步操作,并且它们之间没有依赖关系,使用连续的

await

会导致它们一个接一个地执行,而不是并行执行,从而降低效率。

async function fetchAllDataInefficiently() {    const user = await fetchUser(); // 等待 user 完成    const posts = await fetchPosts(); // 再等待 posts 完成    return { user, posts };}// 正确的做法是并行启动:async function fetchAllDataEfficiently() {    const userPromise = fetchUser();    const postsPromise = fetchPosts();    const user = await userPromise;    const posts = await postsPromise;    return { user, posts };}

这里,

fetchAllDataEfficiently

利用了

Promise.all

的思想,先启动所有异步操作,再等待它们的结果,这比

fetchAllDataInefficiently

更高效。

顶层

await

的环境限制: 在一些较新的JavaScript环境中(如ES模块的顶层),你可以直接使用

await

而不需要将其包裹在

async

函数中。但在传统的脚本文件或CommonJS模块中,直接使用

await

会导致语法错误。

理解

async/await

是Promise的语法糖,并掌握其背后的微任务调度原理,能帮助我们写出更清晰、更高效的异步代码,并避免一些常见的性能陷阱。

以上就是JS如何实现Promise调度?Promise的执行顺序的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1516304.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Web Animation API 滚动驱动动画:从旧语法到新规范的演进与实践
上一篇 2025年12月20日 09:57:06
JS如何实现迭代器?迭代器协议
下一篇 2025年12月20日 09:57:26

相关推荐

  • uc浏览器如何禁止访问某些网站_UC浏览器网站屏蔽与访问限制设置

    uc浏览器如何禁止访问某些网站_UC浏览器网站屏蔽与访问限制设置uc浏览器如何禁止访问某些网站_UC浏览器网站屏蔽与访问限制设置uc浏览器如何禁止访问某些网站_UC浏览器网站屏蔽与访问限制设置uc浏览器如何禁止访问某些网站_UC浏览器网站屏蔽与访问限制设置

    可通过UC浏览器内容过滤、设备家长控制或修改Hosts文件屏蔽网站。首先在UC浏览器中进入“隐私与安全”启用内容过滤并添加自定义屏蔽域名;其次利用手机系统“数字健康”或第三方工具设置网站访问限制,实现跨浏览器管控;最后具备Root权限的用户可编辑/system/etc/hosts文件,添加“0.0.…

    2026年9月24日 用户投稿
    900
  • Bing浏览器怎么使用Web选择_Bing浏览器网页内容选择工具操作

    Bing浏览器怎么使用Web选择_Bing浏览器网页内容选择工具操作Bing浏览器怎么使用Web选择_Bing浏览器网页内容选择工具操作Bing浏览器怎么使用Web选择_Bing浏览器网页内容选择工具操作Bing浏览器怎么使用Web选择_Bing浏览器网页内容选择工具操作

    首先启用Bing浏览器的Web选择工具,点击地址栏右侧图标激活;随后拖动鼠标选择内容,支持多区域选取;最后通过右键复制或使用截图功能保存所选文字、图片等内容。 如果您希望在浏览网页时快速提取或分享特定内容,Bing浏览器的Web选择工具可以帮助您实现精准选取和便捷操作。以下是使用该功能的具体步骤: …

    2026年9月24日 用户投稿
    700
  • Java 正则表达式非贪婪匹配替换:精准替换字符串中的特定部分

    Java 正则表达式非贪婪匹配替换:精准替换字符串中的特定部分Java 正则表达式非贪婪匹配替换:精准替换字符串中的特定部分Java 正则表达式非贪婪匹配替换:精准替换字符串中的特定部分Java 正则表达式非贪婪匹配替换:精准替换字符串中的特定部分

    本文旨在解决 Java 中使用正则表达式进行字符串替换时,如何避免过度匹配,实现对特定字符串的精准替换。通过使用单词边界 ,我们可以确保只替换独立的 $c 字符串,而不会影响到 $c_new 等包含 $c 的其他字符串。本文将提供详细的代码示例和解释,帮助开发者掌握这一技巧。 在 Java 中,使用…

    2026年9月24日 用户投稿
    1000
  • 对话非遗簪花传承人,华硕a豆携豆叮寻香泉州 国庆假期与未来香遇

    对话非遗簪花传承人,华硕a豆携豆叮寻香泉州 国庆假期与未来香遇对话非遗簪花传承人,华硕a豆携豆叮寻香泉州 国庆假期与未来香遇对话非遗簪花传承人,华硕a豆携豆叮寻香泉州 国庆假期与未来香遇对话非遗簪花传承人,华硕a豆携豆叮寻香泉州 国庆假期与未来香遇

    即日起至10月8日,时尚数码潮创先锋华硕a豆于福建泉州限时开启「与未来香遇」 “豆叮的寻香之旅”集章打卡活动,围绕茶桌仔、泉州鲤物、有鲤天台咖啡等三处特色地标打造沉浸式城市寻香狂欢;旗下ip豆叮以头戴非遗簪花的泉州限定皮肤萌力“占领”西街,延续上海安福路街区花车巡游派对的浪漫繁花景象,以“科技与非遗…

    2026年9月24日 用户投稿
    900
  • AI音频工具有哪些_好用的AI音频工具大全

    AI音频工具有哪些_好用的AI音频工具大全AI音频工具有哪些_好用的AI音频工具大全AI音频工具有哪些_好用的AI音频工具大全AI音频工具有哪些_好用的AI音频工具大全

    ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ 魔音工坊:AI配音神器,轻松打造媲美真人声线 讯飞智作:科大讯飞出品的语音转换与配音利器 听脑AI:智能语音记录助手 Suno:高品质AI音乐创作平台 海绵音乐:字节旗下免费AI音乐创作与探索平…

    2026年9月24日 用户投稿
    300
  • Java正则表达式:利用词边界实现精确的非贪婪字符串替换

    Java正则表达式:利用词边界实现精确的非贪婪字符串替换Java正则表达式:利用词边界实现精确的非贪婪字符串替换Java正则表达式:利用词边界实现精确的非贪婪字符串替换Java正则表达式:利用词边界实现精确的非贪婪字符串替换

    本教程探讨如何在Java中使用正则表达式精确替换字符串中的特定部分,特别是在目标字符串不应消耗后续字符的场景。通过分析常见错误,文章详细介绍了词边界的原理与应用,展示了如何利用它实现非贪婪且不破坏原字符串结构的替换,确保匹配的精确性与替换结果的完整性。 在处理字符串替换时,我们经常面临需要精确匹配特…

    2026年9月24日 用户投稿
    700
  • Agent Zero— 开源可扩展AI框架,通过用户指令和任务动态学习

    Agent Zero— 开源可扩展AI框架,通过用户指令和任务动态学习Agent Zero— 开源可扩展AI框架,通过用户指令和任务动态学习Agent Zero— 开源可扩展AI框架,通过用户指令和任务动态学习Agent Zero— 开源可扩展AI框架,通过用户指令和任务动态学习

    agent zero 是一个开源的、可扩展的人工智能框架,能够作为用户的个性化智能助手。它不是基于预设功能的工具,而是通过用户指令和任务来动态学习与成长。agent zero 具备持久记忆能力,可以存储过往的解决方案、代码和事实信息,从而更快速地应对未来的任务。该框架将操作系统视为执行任务的工具,具…

    2026年9月24日 用户投稿
    100
  • 怎么在mysql中创建一个表 mysql新建数据表步骤教程

    在 mysql 中创建表的步骤和建议包括:1. 明确业务需求,设计表结构;2. 使用 create table 语句创建表,选择合适的数据类型和设置主键、索引;3. 考虑大数据量时使用分区;4. 设置正确的字符集和排序规则;5. 谨慎使用索引;6. 使用 if not exists 避免重复创建表。…

    2026年9月24日
    100
  • 主板 BIOS 功能深度对比:哪家超频与调校选项更丰富?

    主板 BIOS 功能深度对比:哪家超频与调校选项更丰富?主板 BIOS 功能深度对比:哪家超频与调校选项更丰富?主板 BIOS 功能深度对比:哪家超频与调校选项更丰富?主板 BIOS 功能深度对比:哪家超频与调校选项更丰富?

    答案是旗舰芯片组主板超频功能更强,具体取决于平台和型号。Intel的Z系列与AMD的X/B650E等高端主板提供完整超频选项,而B/H/A系列则限制较多;微星MPOWER系列在主流芯片组上提供越级超频工具;华硕、微星、技嘉三大品牌在BIOS设计上兼顾易用性与专业性,各具特色;最终选择需结合CPU支持…

    2026年9月24日 用户投稿
    000
  • 百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤

    百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤百度搜索app如何设置默认搜索引擎_百度搜索app搜索引擎切换的详细步骤

    百度App不支持更换默认搜索引擎,用户需通过系统浏览器或第三方浏览器设置。首先检查百度App内“我的-设置”是否有搜索引擎选项;若无,可进入手机系统设置中修改默认浏览器的搜索引擎;或下载如Kiwi Browser、Firefox等支持自定义搜索引擎的浏览器,将其默认搜索设为百度,实现灵活搜索体验。 …

    2026年9月24日 用户投稿
    000
  • Spring Boot @Nested 测试中属性覆盖与隔离策略

    Spring Boot @Nested 测试中属性覆盖与隔离策略Spring Boot @Nested 测试中属性覆盖与隔离策略Spring Boot @Nested 测试中属性覆盖与隔离策略Spring Boot @Nested 测试中属性覆盖与隔离策略

    本文深入探讨了在Spring Boot集成测试中,如何利用@Nested注解结合@TestPropertySource实现细粒度的属性配置和隔离。通过详细的示例代码,展示了外部测试类和嵌套测试类如何定义各自的属性集,以及这些属性在不同测试上下文中的继承与覆盖机制,从而确保测试环境的精确控制和独立性。…

    2026年9月24日 用户投稿
    100
  • 2025拼多多双11力度大吗?2025拼多多新版本

    2025拼多多双11力度大吗?2025拼多多新版本2025拼多多双11力度大吗?2025拼多多新版本2025拼多多双11力度大吗?2025拼多多新版本2025拼多多双11力度大吗?2025拼多多新版本

    拼多多2025年双11延续低价策略,升级百亿补贴、推出超级拼团2.0、发放直播神券、启用AR购物空间并扩容会员特权,覆盖iPhone、家电、美妆等品类,叠加多重优惠与互动玩法提升用户体验。 如果您计划在2025年双11期间购物,可能会关注拼多多此次大促的优惠幅度是否足够吸引人。今年拼多多延续了其“低…

    2026年9月24日 用户投稿
    000
  • sublime怎么安装字体并应用_sublime更换与应用新字体方法

    sublime怎么安装字体并应用_sublime更换与应用新字体方法sublime怎么安装字体并应用_sublime更换与应用新字体方法sublime怎么安装字体并应用_sublime更换与应用新字体方法sublime怎么安装字体并应用_sublime更换与应用新字体方法

    先在操作系统安装字体文件,再通过Sublime Text设置中的font_face指定字体名称即可应用。1. 将.ttf或.otf字体文件安装到系统:Windows右键安装,macOS双击后点击“安装字体”,Linux复制到~/.fonts并运行fc-cache -fv更新缓存。2. 重启Subli…

    2026年9月24日 用户投稿
    100
  • 新增Pro Max旗舰 Civi定位调整:小米手机大变阵为哪般?

    新增Pro Max旗舰 Civi定位调整:小米手机大变阵为哪般?新增Pro Max旗舰 Civi定位调整:小米手机大变阵为哪般?新增Pro Max旗舰 Civi定位调整:小米手机大变阵为哪般?新增Pro Max旗舰 Civi定位调整:小米手机大变阵为哪般?

    2025年,全球智能手机行业步入深度变革阶段。中国信通院最新研究数据显示,今年上半年,国内用户平均换机周期已接近33个月。在市场趋于饱和、增长乏力的背景下,头部手机厂商纷纷开启战略性调整,从产品结构优化到发布节奏重构,一场涵盖苹果、小米、vivo等品牌的“集体转型”正在悄然展开。 据悉,苹果拟对iP…

    2026年9月24日 用户投稿
    000
  • Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法

    Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法Chrome浏览器怎么清理“最近关闭的标签页”列表_“最近关闭”历史记录清除方法

    可通过清除浏览数据、手动删除特定条目或重启浏览器清理“最近关闭的标签页”列表。 如果您在使用Chrome浏览器时希望清理“最近关闭的标签页”列表,以保护隐私或整理浏览历史,可以通过以下多种方法进行操作。 本文运行环境:MacBook Pro,macOS Sonoma 一、清除全部浏览数据以移除最近关…

    2026年9月24日 用户投稿
    100
  • 苹果手机怎么截长图 苹果手机截长图的方法

    苹果手机怎么截长图 苹果手机截长图的方法苹果手机怎么截长图 苹果手机截长图的方法苹果手机怎么截长图 苹果手机截长图的方法苹果手机怎么截长图 苹果手机截长图的方法

    苹果手机截取长图的方法有两种:一是滚动截屏,二是使用第三方应用程序如 Tailor、Stitch It! 或 Scrolling Screenshot。 苹果手机截长图的方法 苹果手机提供了两种截取长图的方法: 方法一:滚动截屏 截取屏幕的第一部分。点击并按住屏幕截图预览。轻扫手指到想要截取的区域末…

    2026年9月24日 用户投稿
    100
  • Android应用中通过下载链接从Firebase Storage下载文件教程

    Android应用中通过下载链接从Firebase Storage下载文件教程Android应用中通过下载链接从Firebase Storage下载文件教程Android应用中通过下载链接从Firebase Storage下载文件教程Android应用中通过下载链接从Firebase Storage下载文件教程

    本教程详细介绍了在Android应用中如何利用文件的下载URL,结合Android DownloadManager将Firebase Storage中的文件下载到用户设备指定目录。内容涵盖必要的运行时权限处理、清单文件配置以及DownloadManager的具体使用方法,旨在帮助开发者实现本地文件存…

    2026年9月24日 用户投稿
    300
  • 163邮箱官网手机免费入口 163免费邮箱移动登录

    163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录163邮箱官网手机免费入口 163免费邮箱移动登录

    163邮箱官网手机免费入口可通过访问mail.163.com自动跳转至移动版,或在应用商店下载“网易邮箱”App登录,支持多账号管理、邮件收发、附件添加、消息推送及多设备同步,并提供登录保护、主题自定义和垃圾邮件过滤等安全与个性化功能。 163邮箱官网手机免费入口在哪里?这是不少网友都关注的,接下来…

    2026年9月24日 用户投稿
    100
  • Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程

    Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程Chrome浏览器书签栏怎么一直显示_设置Chrome书签栏永久显示教程

    通过点击Chrome右上角三点菜单,选择“书签”>“显示书签栏”可恢复书签栏;2. 使用Ctrl+Shift+B(Windows)或Command+Shift+B(Mac)快捷键快速切换显示;3. 在设置页面的“外观”中确保“显示书签栏”设为“始终显示”;4. 若无效,可重置浏览器设置以恢复默…

    2026年9月24日 用户投稿
    200
  • sublime的session文件是做什么用的_sublime会话文件作用与恢复机制

    sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制sublime的session文件是做什么用的_sublime会话文件作用与恢复机制

    Sublime Text的session文件记录了打开的文件、光标位置、代码折叠状态、窗口布局及未保存内容等信息,位于系统特定目录下的Local文件夹中,以JSON格式存储,通过自动保存机制在重启后恢复编辑状态。 Sublime Text 的 session 文件主要用于保存用户当前编辑环境的状态信…

    2026年9月24日 用户投稿
    000

发表回复

登录后才能评论
关注微信