Promise 重复 resolve 引发的 TypeError 解决方式

阅读时长 4 分钟读完

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 错误。

比如下面的代码:

代码中,Promise 对象 p 的状态在第一个 resolve 方法中已经变为 fulfilled,而第二个 resolve 方法就会引发 TypeError 错误。

解决此问题最好的方法是将 resolve 方法的调用放在异步操作的函数体内,并将异步操作改为 Promise,比如下面的代码:

代码中,Promise 对象 p 的状态在异步操作结束后才会变为 fulfilled,可以安全地调用 resolve 方法。

2. 重复在 Promise 上调用 then 方法

如果在一个 Promise 对象上多次调用 then 方法,会在最后一次调用上注册成功回调,前面注册的回调会被覆盖。比如下面的代码:

代码中,Promise 对象 p 的状态在 resolve('a') 调用后即变为 fulfilled,然后在 p 上分别调用了两次 then 方法。第二个 then 方法会覆盖掉第一个 then 方法,只有第二个成功回调会被注册,输出 A

解决此问题的方法是,只在 Promise 对象的链式调用中注册一次回调,或者使用 catch 方法处理错误回调,比如下面的代码:

代码中,使用了链式调用将两个 then 方法合并,输出 aA。同时使用 catch 方法处理错误回调,即使同一个 Promise 对象上多次调用 catch 方法,也不会引发 TypeError 错误。

总结一下,要避免 Promise 重复 resolve 引发的 TypeError 错误,需要将异步操作放在 Promise 的函数体内部,异步操作结束后调用 resolve 方法。同时,在一个 Promise 对象上只调用一次 then 方法,或者使用 catch 方法处理失败回调。这样就能够更加稳定地使用 Promise 实现异步操作。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64757464968c7c53b0284c5a

纠错
反馈