【问题标题】:Argument of type 'Promise<any>' is not assignable to parameter of type 'string''Promise<any>' 类型的参数不可分配给'string' 类型的参数
【发布时间】:2020-10-24 02:29:30
【问题描述】:

在初始化 React 应用程序之前,我会在 localStorage 中获取用户信息。然后,感谢他的 id,我开始与服务器建立套接字连接。

将用户的 id 传递给套接字函数时,typescript 声称:

“Promise”类型的参数不能分配给“字符串”类型的参数

这是我的 index.tsx 文件:

const user = fetchUser();

if (user) {
  getNotifications(user);
}

ReactDOM.render(
      <App />,
  document.getElementById("root")
);

还有 fetchUser() 函数:

export async function fetchUser() {
  try {
    if (!localStorage.getItem("MyAppName")) return null;
    const user = await jwt_decode(localStorage.MyAppName);
    updateUser(user);
    return user.id;
  } catch (err) {
    return null;
  }
}

如何解决这个问题?如果我删除 async/await 它可以工作,但在性能方面,可以在初始化应用程序之前像这样阻塞线程吗?

【问题讨论】:

  • 这样阻塞线程”是什么意思?

标签: reactjs typescript asynchronous promise


【解决方案1】:

getUser 以任何用async 定义的函数的形式返回一个promise,您在解决它之前正在对其进行操作。因为您是在模块全局范围内操作,所以您可以执行以下操作,以非阻塞方式执行:


    getUser.then(user =>  {
       if(user) {
           getNotifications(user);
       }
    })
    .catch(e => console.log('Error: ', e))

【讨论】:

  • 不错的解决方案!鉴于我的用例,您会建议在初始化应用程序之前获取用户并订阅通知,还是像在您的示例中那样以异步方式进行?
  • np,我正在解决提出的具体问题,但是您在哪里调用 getUser 和通知订阅取决于您的实施的更具体细节。在您调用它的任何地方,它将是异步的 - 问题是您是否有任何理由不能在顶级 App 组件中执行此操作,使用钩子/生命周期方法进行调节?在有限的情况下,我不得不将类似的代码放在全局范围内——例如,在 react native 中,在应用程序被杀死后监听后台通知。
  • 是的,你是对的,我将在 中的 useEffect 中进行,就在 browserRouter 的上方。谢谢!
【解决方案2】:

我假设您的 App 以某种方式将通知作为道具。我们希望异步加载通知并允许 App 呈现。获取完成后,App 的道具将更改为包含通知。根据您的应用程序的预期,您可以传递一个空的通知数组,也可以添加一些用作标志的道具,例如isLoadingNotifications,这样您就可以知道在应用程序中呈现微调器而不是通知。

这一切都应该在 一个反应组件中完成。可能在树的下方,但现在让我们将您的 App 包裹在 OuterApp 中。

interface Notification {
  /**... */
}

const OuterApp = () => {

  const [notifications, setNotifications] = useState<Notification[]>([]);

  const loadNotifications = async () => {
    await fetchUser();
    if ( user ) {
      const notes = await getNotifications( user );
      setNotifications( notes );
    }
  }

  useEffect( () => {
     loadNotifications();
    // should probably have a cleanup
  }, [] );

  return (
    <App 
      notifications={notifications}
    />
  )

}

ReactDOM.render(
  <OuterApp />,
  document.getElementById("root")
);

【讨论】:

  • 谢谢。我有一个全局状态管理器,所以我不需要状态和道具。按照您的建议,我只需将 getNotification 添加到 fetchUser() 函数中,并在 内有一个简单的 useEffect(),就在 broswerRouter 上方。
猜你喜欢
  • 2020-03-19
  • 2022-11-30
  • 2019-11-02
  • 1970-01-01
  • 2017-01-30
  • 1970-01-01
  • 2017-02-07
  • 2019-09-06
  • 1970-01-01
相关资源
最近更新 更多