Promise缺点。
1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
当创建一个新的Promise时, 传递给Promise构造函数的执行器函数(executor function)会被立即调用。 这代表Promise代表的异步操作实际上已经开始, 而不是等待某个条件或延迟。这就是立即执行的意思
resolve/reject 这个函数调用本身是同步执行的,它立即将Promise的内部状态从pending 变为 fulfilled(或rejected),并保存值,然后检查是否通过.then()注册了回调函数。 如果有回调:引擎不会立即执行这些回调,而是创建一个微任务(microtask),将这些回调放入到微任务队列;微任务队列会在当前执行栈清空后、下一个宏任务开始前被依次同步处理。
严格来说:resolve 本身并不在微任务中执行,它只是触发将then 回调排入微任务队列的动作。回调函数的执行才是真正发生在微任务中的。
js
const executor = (resolve, reject) => {
console.log('执行器内代码');
resolve('完成');
};
const p = new Promise(executor);
// promise 内部构造函数如下:
function Promise (executor){
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
// 所以Promise构造函数的 executor 参数是立即执行的,是同步执行的, 无法在它运行之后再去"取消"
2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
如果不设置回调函数 (.catch或 .then的第二个参数)内部抛出的错误不会反应到外部。 即使 try...catch; 错误会被吞噬,(仅表现为未处理的rejection 警告);
arduino
promise的错误处理机制:Promise 内部的错误(包括执行器函数中的 throw 或 reject)
会被Promise内部捕获并转化为rejected 状态; 如果没有.catch 或.then的第二个参数处理这个rejection,
那么该错误就会被"吞没", 不会冒泡到外部同步代码 try...catch
js
(async () => {
try {
await new Promise((resolve, reject) => {
throw new Error('内部错误'); // 或者 reject('内部错误')
});
} catch (err) {
console.log('捕获到:', err);
}
})();
//这种方式可以捕获到同步错误
try...catch 包裹 new Promise 无法捕获内部抛出的错误, 因为Promise构造函数
内部已经将错误捕获并转换为rejection。
如果错误是在then回调中抛出的, 且没有.catch, 同样会被吞没。
原因在于: Promise内部已经自己拦截了错误(无论通过throw 还是reject),并将它转换为rejected状态。外层的 try...catch 只能捕获同步代码执行过程中的即时抛出的错误;而Promise内部的错误是异步传递的。所以完全绕过了外层的 try...catch**"异步处理" 指的是:Promise 内部发生的错误(无论是同步 throw 还是 reject)不会被立即向外抛出,而是被转换为一个 rejected 状态的 Promise,其错误处理回调(如
.catch)会在当前调用栈清空后的微任务阶段执行。** 这种从"同步抛出"到"微任务处理"的转变,就是异步性的核心体现。
3 .第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
Promise对象的错误传递
1. Promise对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止。
如果某个Promise rejected, 会沿着链式调用传递到下一个catch;
Promise 内部构造函数内部 会try...catch 执行器函数的同步错误,一但捕获到就会调用内部的reject函数将错误转为rejected 状态,这是向后传递的起点。executor中抛出的错误被捕获后并没有被吞掉,而是通过reject()传递给了Promise对象, 然后该Promise对象的rejected状态就会沿着链传递到下一个catch
异步回调中抛出错误(setTimeout 里 throw)无法被Promise 捕获,甚至会导致程序崩溃;没有外层的try...catch 会直接抛出到全局;
then 回调是微任务,并且Promise要求实现必须用 try...catch 包裹每个回调;所以同步错误会被转化为 rejection
setTimeout 回调时宏任务,由事件循环直接调用;没有外层的try-catch 因此会直接抛出到全局环境; 效果图

在Promise的onFulfilled 或onRejected 中 任何同步抛出的值(无论是显式 throw 还是隐式的运行时异常)都会导致返回的新Promise 变为rejected;
js
//1. 运行时错误,这种属于隐式的抛出错误;
Promise.resolve({})
.then(obj => {
obj.a.b; // 抛出 TypeError
})
.catch(err => {
console.log('捕获到:', err); // 输出:TypeError: Cannot read property 'b' of undefined
});
// 2. 显式抛出错误;
throw new Error('xxx');
// 两者行为完全一致,都是抛出一个错误对象(或任意值)。
// Promise的机制不关系错误是 显式throw的还是 隐式运行时产生的,
// 它只关心在回调执行过程中是否有未捕获的异常被抛出; 只要有,都会转化为rejected
// 3. 语法报错 不会进入回调;因为脚本在解析阶段就失败了;
Promise.resolve().then(() => {
if(true {return 1}
})
js
throw new Error(123) 与 new Erro(123) 的区别
1. throw new Error(123) 会抛出异常,中断当前函数执行
2. new Erro(123) 仅仅创建了一个Error对象实例,不会产生任何副作用,程序继续执行;(不影响后续代码,因为没抛出)
PromiseA 、PromiseA+ 、 ES6 Promise 之间的关系
PromiseA
- 提出者:CommonJS 社区
- 地位与作用:该领域的早期规范,奠定了Promise的核心概念(如状态机、then方法),但部分细节定义模糊
- 局限性与评价: 作为"开路先锋",它为后来的标准指明了方向,但其自身并不算完美;
PromiseA+
- 提出者:社区开发者(基于Promise/A的改进)
- 地位与作用:事实上的行业标准。它严格定义了 .then()链式调用的核心机制(称为thenable),并提供了详尽的兼容性测试套件
- 局限性与评价:作为一个"最小化规范", 它只关心then方法,并未规定如何创建Promise实例; 也没有定义catch、finally, all 等便捷方法
ES6规范(官方标准)
- 提出者:ECMA国际组织(TC39委员会)
- 地位与作用:JS语言的官方标准,实现了Promise的大统一
- 局限性与评价:完全遵守Promise/A+的核心then行为,确保与各类Promise库互相操作。同时不起了catch,finally, all, race 等全套API
简单来说:Promise/A+ 是对Promise/A 的改进和完善, 而ES6 Promise又全盘采纳了Promise/A+的行为准则。
js
什么是thenable
指的是任何拥有then方法的对象或函数。简单来说只要一个东西又.then方法,就是thenable;
它是Promise生态中实现互操作性的基石。让来自不同库的异步对象能够无缝协作。ES6 Promise完全遵循这一设计;
// 这是一个 thenable
const thenable = {
then: function(onFulfilled, onRejected) {
}
}
// 这也是一个thenable
function foo () {}
foo.then = function(onFulfilled) { onFulfilled(42) };
// Promise/A+ 规范没有规定如何创建Promise(留给具体实现), 但是规定了一个同意的互操作机制,
// 任何Promise实现(ES6 Promise、 BlueBird、 Q、 $q等)都应该能无缝处理其他库返回的thenable
具体来说:
Promise.resolve(value) 如果遇到一个thenable, 不会直接把它当作普通值包装,
而是展开它:调用它的then 方法,并把自己的状态绑定到该thenable的结果上。
这样不同的Promise库之间可以互相消费对方返回的 类Promise对象。实现兼容;
const qPromise = Q.delay(100).then(() => 'done');
Promise.resolve(qPromise).then(val => {
console.log(val); // 'done'
});

Promise 链返回值规则
js
1. then/catch 返回一个新Promise
2. 回调返回值决定新Promise 状态。
返回普通值-> resolved,值传递下去
返回Promise -> 新Promise跟随该Promise的状态
抛出异常(或返回rejected Promise)-> rejected, 错误传递下去
Promise 错误传递机制
js
1. 链中任一环节的rejection 会向后传递, 直到遇到第一个catch 或then的失败回调;
2. catch本质是 then(null, onRejected)
3. 若未捕获,最终触发unhandledrejection 事件;