Promise 重复 resolve 引发的 TypeError 解决方式
在使用 Promise 进行异步操作时,经常会看到以下代码:
-- -------------------- ---- ------- ----- - - --- ----------------- ------- -- - -- ---- -------------- -- ------------ -- - -- ---- -------------- -- - -- ---- --
这段代码的含义是:创建一个 Promise 对象 p
,异步操作完成后调用 resolve
方法,将结果 value
传入。在 p
上调用 then
方法,注册成功回调。如果异步操作抛出错误,则 reject
方法将会被调用,会在 p
上调用 catch
方法,注册失败回调。这样就可以异步完成一些操作,同时处理成功和失败的情况。
然而,有些人会遇到 TypeError 的错误,提示 Promise 已经完成过,并且不能再次完成。这一般有两种情况:
1. 重复在 Promise 中调用 resolve 方法
首先,需要区分 Promise 对象的状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。如果一个 Promise 对象状态已经变为 fulfilled 或 rejected,再次调用 resolve 或 reject 方法就会引发 TypeError 错误。
比如下面的代码:
const p = new Promise((resolve, reject) => { resolve('a'); resolve('b'); }); p.then(value => console.log(value));
代码中,Promise 对象 p
的状态在第一个 resolve
方法中已经变为 fulfilled,而第二个 resolve
方法就会引发 TypeError 错误。
解决此问题最好的方法是将 resolve 方法的调用放在异步操作的函数体内,并将异步操作改为 Promise,比如下面的代码:
const p = new Promise((resolve, reject) => { setTimeout(() => { resolve('a'); }, 1000); }); p.then(value => console.log(value));
代码中,Promise 对象 p
的状态在异步操作结束后才会变为 fulfilled,可以安全地调用 resolve 方法。
2. 重复在 Promise 上调用 then 方法
如果在一个 Promise 对象上多次调用 then 方法,会在最后一次调用上注册成功回调,前面注册的回调会被覆盖。比如下面的代码:
const p = new Promise((resolve, reject) => { resolve('a'); }); p.then(value => console.log(value)); p.then(value => console.log(value.toUpperCase()));
代码中,Promise 对象 p
的状态在 resolve('a')
调用后即变为 fulfilled,然后在 p 上分别调用了两次 then 方法。第二个 then 方法会覆盖掉第一个 then 方法,只有第二个成功回调会被注册,输出 A
。
解决此问题的方法是,只在 Promise 对象的链式调用中注册一次回调,或者使用 catch 方法处理错误回调,比如下面的代码:
const p = new Promise((resolve, reject) => { resolve('a'); }); p.then(value => { console.log(value); return value.toUpperCase(); }).then(value => console.log(value)) .catch(error => console.error(error));
代码中,使用了链式调用将两个 then 方法合并,输出 a
和 A
。同时使用 catch 方法处理错误回调,即使同一个 Promise 对象上多次调用 catch 方法,也不会引发 TypeError 错误。
总结一下,要避免 Promise 重复 resolve 引发的 TypeError 错误,需要将异步操作放在 Promise 的函数体内部,异步操作结束后调用 resolve 方法。同时,在一个 Promise 对象上只调用一次 then 方法,或者使用 catch 方法处理失败回调。这样就能够更加稳定地使用 Promise 实现异步操作。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64757464968c7c53b0284c5a