如果你的项目使用的是 es6-promise 运行下面代码,是不会抛出错误的。
const p1 = new Promise((resolve) => {
resolve(1)
}).then(data => {
console.log("first then")
}).then(data => {
console.log("second then start")
const d = 0;
d = 9;
console.log("second then end")
})
运行结果
上述代码运行到这里的时候,是会报一个 Error: "d" is read-only 错误的,但是这个错误不会现实中 console 控制台中。
const d = 0;
d = 9;
因此,我只能debug 一下源码,当运行到 ,其实就是在调用 invokeCallback 方法 (已经删除部分无关代码)
const d = 0;
d = 9;
invokeCallback
function tryCatch(callback, detail) {
try {
return callback(detail);
} catch(e) {
TRY_CATCH_ERROR.error = e;
return TRY_CATCH_ERROR;
}
}
function invokeCallback(settled, promise, callback, detail) {
let hasCallback = isFunction(callback),
value, error, succeeded, failed;
if (hasCallback) {
// ①执行callback ,触发 "d" is read-only 错误,然后把错误存储在 TRY_CATCH_ERROR.error 里面
value = tryCatch(callback, detail);
if (value === TRY_CATCH_ERROR) {
failed = true;
error = value.error;
value.error = null;
} else {
succeeded = true;
}
} else {
}
if (promise._state !== PENDING) {
// noop
} else if (hasCallback && succeeded) {
resolve(promise, value);
} else if (failed) {
//②执行 reject 方法,error 就是 TRY_CATCH_ERROR.error 存储的 "d" is read-only 错误
reject(promise, error);
} else if (settled === FULFILLED) {
fulfill(promise, value);
} else if (settled === REJECTED) {
reject(promise, value);
}
}
执行 invokeCallback 方法,发生了两件事情。
①执行callback ,触发 "d" is read-only 错误,然后把错误存储在 TRY_CATCH_ERROR.error 里面
② 执行 reject 方法,error 就是 TRY_CATCH_ERROR.error 存储的 "d" is read-only 错误
resolve
function reject(promise, reason) {
if (promise._state !== PENDING) { return; }
// 改变当前promise 的状态
promise._state = REJECTED;
// 把当前 promise 的值设置为 "d" is read-only 的 error
promise._result = reason;
asap(publishRejection, promise);
}
publishRejection
function publishRejection(promise) {
if (promise._onerror) {
promise._onerror(promise._result);
}
// 执行 publish
publish(promise);
}
publish
function publish(promise) {
let subscribers = promise._subscribers;
let settled = promise._state;
// ③ subscribers 为空,直接返回
if (subscribers.length === 0) { return; }
let child, callback, detail = promise._result;
for (let i = 0; i < subscribers.length; i += 3) {
child = subscribers[i];
callback = subscribers[i + settled];
if (child) {
invokeCallback(settled, child, callback, detail);
} else {
callback(detail);
}
}
promise._subscribers.length = 0;
}
publish 就是执行 subscribers 里面的promise,但是由于此例子中,报错的then 后面已经没有then了,subscribers 为空,所以运行到③ , publish 直接返回。
所以解决方法也很简单,就是,在后面再加一个 then , 或catch
const p1 = new Promise((resolve) => {
resolve(1)
}).then(data => {
console.log("first then")
}).then(data => {
console.log("second then start")
const d = 0;
d = 9;
console.log("second then end")
}).then(() => { }, (e) => {
console.log(e)
})