You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用expo-contacts获取联系人时pending callbacks过多错误的解决方法

解决Expo Contacts获取联系人时的"Excessive number of pending callbacks"错误

这个错误通常源于未限制useEffect执行时机(重复触发异步操作)、未正确等待异步方法完成,以及组件卸载后仍有异步回调尝试更新状态导致的回调泄漏。以下是具体解决步骤和优化后的代码:

关键修复点

  • 给useEffect添加空依赖数组[],确保仅在组件挂载时执行一次,避免重复触发异步操作积累回调。
  • 为Contacts.getContactsAsync()添加await,该方法是异步的,必须等待完成才能获取有效数据,否则会产生未处理的Promise导致泄漏。
  • 使用AbortController取消未完成的异步请求,防止组件卸载后回调继续执行。
  • 统一用async/await处理AsyncStorage操作,简化逻辑并便于错误处理。

优化后的完整代码

import * as Contacts from 'expo-contacts';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useEffect, useState } from 'react';

function ContactListScreen() {
  const [contacts, setContacts] = useState([]);
  const [phone, setPhone] = useState(null);
  const [name, setName] = useState(null);

  useEffect(() => {
    const abortController = new AbortController();
    const signal = abortController.signal;

    const fetchData = async () => {
      try {
        // 请求联系人权限
        const { status } = await Contacts.requestPermissionsAsync();
        if (status === 'granted') {
          // 等待联系人获取完成,传入signal支持取消
          const { data } = await Contacts.getContactsAsync({
            fields: [Contacts.Fields.PhoneNumbers],
            signal,
          });
          if (data.length > 0) {
            setContacts(data);
          }
        }

        // 获取本地存储的凭证
        const result = await AsyncStorage.getItem('Credentials');
        if (result !== null) {
          const credentials = JSON.parse(result);
          setPhone(credentials.phone);
          setName(credentials.fullName);
        } else {
          setPhone(null);
        }
      } catch (error) {
        // 忽略取消操作的错误,避免控制台冗余报错
        if (error.name !== 'AbortError') {
          console.error('数据获取失败:', error);
        }
      }
    };

    fetchData();

    // 组件卸载时取消所有未完成的异步操作
    return () => abortController.abort();
  }, []); // 空依赖数组,确保仅执行一次

  // 你的组件UI渲染逻辑
  return (
    // ... 此处为UI代码
  );
}

额外说明

  • 如果你的联系人数量极大,还可以考虑使用Contacts.getContactsAsync的pageSize和page参数进行分页获取,避免一次性加载大量数据导致的性能问题和回调堆积。
  • 若仍出现问题,检查是否有其他未清理的异步操作或重复触发的useEffect,确保所有异步逻辑都有明确的执行时机和清理机制。

内容的提问来源于stack exchange,提问作者bytebunny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 17:20:59