Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Promise 这个新 API 真香!

Promise 这个新 API 真香!

作者头像
沉浸式趣谈
发布于 2025-04-26 12:24:11
发布于 2025-04-26 12:24:11
8100
代码可运行
举报
文章被收录于专栏:沉浸式趣谈沉浸式趣谈
运行总次数:0
代码可运行
  • • Hey, 我是 沉浸式趣谈
  • • 本文首发于【沉浸式趣谈】,我的个人博客 https://yaolifeng.com 也同步更新。
  • • 转载请在文章开头注明出处和版权信息。
  • • 如果本文对您有所帮助,请 点赞评论转发,支持一下,谢谢!

聊到异步,Promise 大家肯定都不陌生,是咱们处理异步操作的神器

不过呢,就算有 Promise,有时候处理一些既可能是同步又可能是异步的函数,或者那种随时可能在启动时就给你扔个同步错误的函数,还是有点小别扭。

你懂的,就是那种“我想用 .then().catch() 一把梭,但又怕它在 Promise 链开始前就崩了”的尴尬。

好消息来了!

ES2025 憋了个大招 —— Promise.try()

Promise.try() 到底是何方神圣?

说白了,它就是 Promise 上的一个静态方法,像个万能启动器。

你扔给它一个函数(管它是同步的、异步的,会返回值还是会抛错),它都能稳稳地给你包成一个 Promise。

代码大概长这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.try(你要运行的函数, ...可能需要的参数);

简单粗暴,对吧?

关键在于,它特别擅长处理那些“不确定性”。

比如:

  • • 如果你的函数是同步的,执行完直接返回值 X?那 Promise.try() 就给你一个 resolved 状态、值为 X 的 Promise。
  • • 要是函数同步执行时直接 throw new Error() 了呢?(这种最头疼了,以前可能直接崩掉后续代码)Promise.try() 会捕获这个错误,然后给你一个 rejected 状态的 Promise,错误就在里面,你可以用 .catch() 接住。简直完美!
  • • 那如果函数本身就返回一个异步的 Promise 呢?没问题,Promise.try() 就直接用那个 Promise 的状态。

为啥我们需要这玩意儿?以前不也活得好好的?

嗯... 活得好是好,但可能不够优雅,或者说,不够省心。

记得以前咱们想统一处理同步/异步函数时,可能会用 Promise.resolve().then(func) 这招吗?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const f = () => console.log('我应该立刻执行!');
Promise.resolve().then(f); // 但它被塞到微任务队列里去了
console.log('我先执行了...');
// 输出:
// 我先执行了...
// 我应该立刻执行!

明明 f 是个同步函数,结果被 then 这么一搞,硬生生变成了异步执行。

有时候我们并不想要这种延迟。而且,如果 f 本身在执行前就抛错,Promise.resolve() 可管不了。

Promise.try() 就是来解决这个痛点的。

它能让你的函数(如果是同步的)基本上是立即尝试执行,同时还保证了无论如何你都能拿到一个 Promise,并且同步错误也能被链式捕获。

...呃,或者更准确地说,它提供了一个统一的、更安全的 Promise 启动方式。

来,上代码感受下

  • 搞定同步函数:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const syncTask = () => {
    console.log('同步任务跑起来~');
    return '同步搞定';
};

Promise.try(syncTask)
    .then(res => console.log('结果:', res)) // 立刻输出 "同步搞定"
    .catch(err => console.error('出错了?', err));
// 控制台会先打印 "同步任务跑起来~",然后是 "结果: 同步搞定"
  • 处理异步函数(这个没啥特别,就是正常用):
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const asyncTask = () => new Promise(resolve => setTimeout(() => resolve('异步也 OK'), 500));

Promise.try(asyncTask)
    .then(res => console.log('结果:', res)) // 大约 500ms 后输出 "异步也 OK"
    .catch(err => console.error('出错了?', err));
  • 最妙的地方:捕获同步错误
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const potentiallyExplodingTask = () => {
    if (Math.random() < 0.5) {
        // 假设这里有 50% 概率直接炸
        thrownewError('Boom! 同步错误');
    }
    return'安全通过';
};

// 多试几次你就能看到效果
Promise.try(potentiallyExplodingTask)
    .then(res =>console.log('这次运气不错:', res))
    .catch(err =>console.error('捕获到错误:', err.message)); // 能抓住那个 "Boom!"

就算 potentiallyExplodingTaskPromise 链条“正式”开始前就同步抛错了,Promise.try() 也能稳稳接住,交给你后面的 .catch() 处理。

这在以前,可能就直接导致程序崩溃或者需要写额外的 try...catch 块了。(这点我个人觉得超级实用!)

这东西有啥好的?总结一下哈:

  1. 1. 入口统一: 不管三七二十一,同步异步函数塞进去,出来的都是 Promise,后续处理逻辑可以写得非常一致。代码看着就清爽多了。
  2. 2. 同步错误保险: 这是重点!能捕获启动函数时的同步错误,塞到 Promise 链里,让你用 .catch() 一勺烩了。避免了裸露的 try...catch 或者漏抓错误的风险。
  3. 3. 可读性提升: 意图更明显,一看 Promise.try() 就知道这里是安全启动一个可能同步也可能异步的操作。

实战中能怎么玩?

API fetch 本身返回 Promise,但之前的 URL 处理、参数构造啥的可能是同步的,万一出错呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 以前的写法
functionfetchUserData(userId) {
    try {
        // 这里的 buildApiUrl 可能会同步抛出错误
        const url = buildApiUrl(`/users/${userId}`);
        returnfetch(url).then(res => res.json());
    } catch (err) {
        returnPromise.reject(err); // 手动转换成 Promise 错误
    }
}

// 使用 Promise.try 的写法
functionfetchUserData(userId) {
    returnPromise.try(() => {
        const url = buildApiUrl(`/users/${userId}`);
        returnfetch(url).then(res => res.json());
    });
}

// 调用示例
fetchUserData('123')
    .then(data =>console.log('用户数据:', data))
    .catch(err =>console.error('获取用户数据失败:', err));
  • • 用 Promise.try(() => fetch(buildUrl(params))) 就很稳。

混合任务链: 比如先跑个同步任务,再根据结果跑个异步任务,用 Promise.try(syncTask).then(res => Promise.try(() => asyncTask(res))) 串起来就很自然。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 假设我们有个处理用户输入的场景
functionvalidateInput(input) {
    // 同步验证,可能会抛出错误
    if (!input || input.length < 3) {
        thrownewError('输入太短了!');
    }
    return input.trim().toLowerCase();
}

functionsaveToDatabase(processedInput) {
    // 异步保存,返回 Promise
    returnnewPromise((resolve, reject) => {
        setTimeout(() => {
            if (processedInput === 'admin') {
                reject(newError('不能使用保留关键字'));
            } else {
                resolve({ success: true, id: Date.now() });
            }
        }, 500);
    });
}

// 使用 Promise.try 组合这两个任务
functionprocessUserInput(rawInput) {
    returnPromise.try(() =>validateInput(rawInput)).then(validInput =>
        Promise.try(() =>saveToDatabase(validInput))
    );
}

// 测试不同情况
processUserInput('') // 同步错误
    .then(result =>console.log('保存成功:', result))
    .catch(err =>console.error('处理失败:', err.message));

processUserInput('admin') // 异步错误
    .then(result =>console.log('保存成功:', result))
    .catch(err =>console.error('处理失败:', err.message));

processUserInput('user123') // 成功情况
    .then(result =>console.log('保存成功:', result))
    .catch(err =>console.error('处理失败:', err.message));

数据库/文件操作: 很多库的 API 设计可能五花八门,有的同步出错有的异步出错,用 Promise.try 包裹一下,可以简化错误处理逻辑。(当然,具体库可能有自己的最佳实践,这只是个思路)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 假设我们有个文件操作库,它的 API 设计有点混乱
const fileOps = {
    readConfig(path) {
        // 这个方法可能同步抛错(比如路径格式不对)
        // 也可能返回 Promise(实际读取文件时)
        if (!path.endsWith('.json')) {
            thrownewError('配置文件必须是 JSON 格式');
        }

        returnnewPromise((resolve, reject) => {
            setTimeout(() => {
                if (path.includes('nonexistent')) {
                    reject(newError('文件不存在'));
                } else {
                    resolve({ version: '1.0', settings: { theme: 'dark' } });
                }
            }, 100);
        });
    },
};

// 不使用 Promise.try 的话,调用方需要自己处理同步错误
functionloadAppConfig_old(configPath) {
    try {
        return fileOps.readConfig(configPath).then(config => {
            console.log('配置加载成功');
            return config;
        });
    } catch (err) {
        console.error('同步错误:', err);
        returnPromise.reject(err);
    }
}

// 使用 Promise.try,代码更简洁,错误处理更统一
functionloadAppConfig(configPath) {
    returnPromise.try(() => fileOps.readConfig(configPath)).then(config => {
        console.log('配置加载成功');
        return config;
    });
}

// 测试各种情况
loadAppConfig('settings.txt') // 同步错误 - 非 JSON 文件
    .catch(err =>console.error('加载失败:', err.message));

loadAppConfig('nonexistent.json') // 异步错误 - 文件不存在
    .catch(err =>console.error('加载失败:', err.message));

loadAppConfig('settings.json') // 成功情况
    .then(config =>console.log('配置内容:', config))
    .catch(err =>console.error('加载失败:', err.message));

聊了这么多,总而言之...

Promise.try() 这哥们儿,虽然看起来只是个小补充,但它解决的痛点可是实实在在的。

它让 Promise 的使用,尤其是在链条的起点上,变得更健壮、更统一。

我个人感觉,一旦大家习惯了它带来的便利(特别是那个同步错误捕获!),估计很快就会成为咱们工具箱里的常客了。

有机会的话,真得试试看!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 非同质前端札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Promise 这个新 API 真香!
不过呢,就算有 Promise,有时候处理一些既可能是同步又可能是异步的函数,或者那种随时可能在启动时就给你扔个同步错误的函数,还是有点小别扭。
沉浸式趣谈
2025/04/28
1020
Promise 必知必会(十道题)
Promise 想必大家都十分熟悉,想想就那么几个 api,可是你真的了解 Promise 吗?本文根据 Promise 的一些知识点总结了十道题,看看你能做对几道。
Nealyang
2019/11/24
6040
重学JavaScript Promise API
在JavaScript中,一些操作是异步的。这意味着当这些操作完成时,它们产出的结果或者值并不会立即生效。
chuckQu
2023/09/01
2480
重学JavaScript Promise API
Javascript[0x07] -- Promise初探
注意: 状态一旦转换将不可逆, 返回的是一个promise对象,并不是所有都支持promise
江涛学编程
2020/06/19
5820
promise & axios & async_await 关于 Promise
Promise 是ES6里面异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。 简单说Promise 就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。 有三种状态,pending(进行中)、resolved(已完成)、rejected(已失败),特点是只有异步操作的结果,可以决定当前是哪一种状态,状态一旦改变,就无法再次改变状态;
前端小tips
2021/11/24
1.6K0
promise & axios & async_await 关于 Promise
【Web前端】Promise的使用
Promise 是一个代表异步操作最终完成(或失败)及其结果值的对象。它有三种状态:
一条晒干的咸鱼
2024/11/19
2170
【Web前端】Promise的使用
NodeJS的异常捕获
由于nodejs是非阻塞单进程单线程的,一旦nodejs抛出异常,整个服务就会停掉。服务将会非常不稳定。
码客说
2021/09/01
6.4K0
15道ES6 Promise实战练习题,助你快速理解Promise
Promise是ES6中新增的特性,现在很多前端框架像AngularJS,Vue等在HTTP请求之后都是返回的Promise处理,因此Promise是必须要掌握的一个知识点。
winty
2021/01/05
2.3K0
[前端学习]Promise 对象一网打尽
Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
Maynor
2021/12/07
1K0
JavaScript Promise
  我们都知道 JavaScript 是一种同步编程语言,上一行出错就会影响下一行的执行,但是我们需要数据的时候总不能每次都等上一行执行完成,这时就可以使用回调函数让它像异步编程语言一样工作。   像 NodeJS 就是采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行不用在某个地方等待着。但是也有一个不好的地方,当我们有很多回调的时候,比如这个回调执行完需要去执行下个回调,然后接着再执行下个回调,这样就会造成层层嵌套,代码不清晰,很容易进入“回调监狱”。。。   所以 ES6 新出的 Promise 对象以及 ES7 的 async、await 都可以解决这个问题。   Promise 是用来处理异步操作的,可以让我们写异步调用的时候写起来更加优雅,更加美观便于阅读。Promise 为承诺的意思,意思是使用 Promise 之后他肯定会给我们答复,无论成功或者失败都会给我们一个答复,所以我们就不用担心他跑了哈哈。   Promise 有三种状态:pending(未决定),resolved(完成fulfilled),rejected(失败)。只有异步返回时才可以改变其状态,因此我们收到的 Promise 过程状态一般只有两种:pending->fulfilled 或者 pending->rejected。
老猫-Leo
2023/12/11
3260
JavaScript Promise
consolewriteline用法_promise sb to do
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
全栈程序员站长
2022/09/19
4200
【译】《Understanding ECMAScript6》- 第七章-Promise
目录 异步编程 Promise基础 链式Promise 多重Promise响应 Promise继承 总结 异步操作是JavaScript最强大的功能之一。JavaScript的设计初衷是作为一种面向web的语言,因此具备响应用户行为(比如鼠标和键盘事件)的功能。Node.js使用回调函数代替事件驱动,进一步强化了JavaScript语言的异步编程能力。但是,随着异步编程被广泛使用,开发者们发现这两种异步模式(事件驱动和回调函数)并不能满足所有的产品需求。在这样的背景下,Promise应运而生。 Promis
寒月十八
2018/01/30
2.2K0
这 10 个片段,有助于你理解 ES 中的 Promise
在开发中,了解 JavaScript 和 Promise 基础,有助于提高我们的编码技能,今天,我们一起来看看下面的 10 片段,相信看完这 10 个片段有助于我们对 Promise 的理解。
前端小智@大迁世界
2020/05/11
6550
Vue笔记:封装 axios 为插件使用
自从Vue2.0推荐大家使用 axios 开始,axios 被越来越多的人所了解。使用axios发起一个请求对大家来说是比较简单的事情,但是axios没有进行封装复用,项目越来越大,引起的代码冗余。就会非常麻烦的一件事。所以本文会详细的跟大家介绍,如何封装请求,并且在项目组件中复用请求。有需要的朋友可以做一下参考。
朝雨忆轻尘
2019/06/19
2K0
Vue笔记:封装 axios 为插件使用
Promise与Async/Await:异步编程的艺术
一个Promise对象代表了一个现在、将来或永远可能可用,也可能不可用的值。它有三种状态:pending(进行中)、fulfilled(已成功)或rejected(已失败)。
空白诗
2024/06/14
2370
Promise用法详解(一)
注意:上面new出来promise,只代表形式上的一个异步操作。就是说,我们只知道他是一个 异步操作,但做什么具体异步事情目前还不清楚。
全栈程序员站长
2022/07/04
3920
Promise用法详解(一)
[译]深入Promise错误处理
原文: https://codeburst.io/promise-error-handling-in-depth-90b0965149c0
江米小枣
2020/06/15
4530
【ECMAScript6】es6 要点(二)Promise | 自个写一个Promise | Generator | Async/Await
但是,我们不能无限制地调用next从Generator实例中获取值。否则最后会返回undefined。原因:Generator犹如一种序列,一旦序列中的值被消费,你就不能再次消费它。即,序列为空后,再次调用就会返回undefined!。
前端修罗场
2023/10/07
3210
【ECMAScript6】es6 要点(二)Promise | 自个写一个Promise | Generator | Async/Await
关于 JavaScript 错误处理的最完整指南(下半部)
相对简单抛出异常,我们可以使用 Promise.reject 和Promise.resolve:
前端小智@大迁世界
2020/09/17
2.4K0
ES6中的Promise对象作用
在JS开发中,异步函数是一个绕不过去的坎,要想写出优雅适用的js代码,把异步函数的使用技巧掌握透是必须的。
前端_AWhile
2019/08/29
8880
相关推荐
Promise 这个新 API 真香!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验