错误处理 #

常见错误类型 #

HTTP状态码 #

状态码 说明 处理方式
400 请求参数错误 检查参数格式
401 认证失败 检查API密钥
403 权限不足 检查密钥权限
404 资源不存在 检查索引名称
429 请求过多 实现限流
500 服务器错误 重试请求

错误响应结构 #

javascript
{
  "message": "Index not found",
  "status": 404,
  "name": "ApiError"
}

错误处理策略 #

基本错误处理 #

javascript
try {
  const results = await index.search('iphone');
} catch (error) {
  console.error('Search failed:', error.message);
  console.error('Status:', error.status);
}

按状态码处理 #

javascript
async function safeSearch(query) {
  try {
    return await index.search(query);
  } catch (error) {
    switch (error.status) {
      case 400:
        console.error('请求参数错误:', error.message);
        return { hits: [], nbHits: 0 };
      
      case 401:
        console.error('API密钥无效');
        throw new Error('认证失败');
      
      case 403:
        console.error('权限不足');
        throw new Error('无访问权限');
      
      case 404:
        console.error('索引不存在');
        return { hits: [], nbHits: 0 };
      
      case 429:
        console.error('请求过多,稍后重试');
        await sleep(1000);
        return safeSearch(query);
      
      default:
        console.error('未知错误:', error);
        throw error;
    }
  }
}

重试机制 #

简单重试 #

javascript
async function retrySearch(query, maxRetries = 3) {
  let lastError;
  
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await index.search(query);
    } catch (error) {
      lastError = error;
      
      // 客户端错误不重试
      if (error.status >= 400 && error.status < 500) {
        throw error;
      }
      
      // 指数退避
      await sleep(1000 * Math.pow(2, i));
    }
  }
  
  throw lastError;
}

带退避的重试 #

javascript
async function searchWithBackoff(query, options = {}) {
  const {
    maxRetries = 3,
    initialDelay = 1000,
    maxDelay = 30000
  } = options;
  
  let delay = initialDelay;
  
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await index.search(query);
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      
      // 只重试服务端错误
      if (error.status >= 500 || error.status === 429) {
        await sleep(delay);
        delay = Math.min(delay * 2, maxDelay);
      } else {
        throw error;
      }
    }
  }
}

降级策略 #

返回缓存数据 #

javascript
async function searchWithFallback(query) {
  try {
    const results = await index.search(query);
    cacheResults(query, results);
    return results;
  } catch (error) {
    console.error('Search failed, using cache:', error.message);
    
    const cached = getCachedResults(query);
    if (cached) {
      return cached;
    }
    
    return { hits: [], nbHits: 0 };
  }
}

返回默认数据 #

javascript
async function searchWithDefault(query) {
  try {
    return await index.search(query);
  } catch (error) {
    console.error('Search failed:', error.message);
    
    return {
      hits: [],
      nbHits: 0,
      page: 0,
      nbPages: 0,
      error: true
    };
  }
}

前端错误处理 #

React错误边界 #

jsx
class SearchErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  
  componentDidCatch(error, info) {
    console.error('Search error:', error, info);
  }
  
  render() {
    if (this.state.hasError) {
      return (
        <div className="error-fallback">
          <p>搜索出现错误,请稍后重试</p>
          <button onClick={() => this.setState({ hasError: false })}>
            重试
          </button>
        </div>
      );
    }
    
    return this.props.children;
  }
}

// 使用
<SearchErrorBoundary>
  <SearchComponent />
</SearchErrorBoundary>

用户友好提示 #

javascript
function getErrorMessage(error) {
  const messages = {
    400: '搜索参数有误,请检查输入',
    401: '请重新登录后再试',
    403: '您没有权限执行此操作',
    404: '未找到相关内容',
    429: '请求过于频繁,请稍后再试',
    500: '服务器繁忙,请稍后再试'
  };
  
  return messages[error.status] || '搜索失败,请稍后重试';
}

调试技巧 #

启用调试日志 #

javascript
const client = algoliasearch('APP_ID', 'API_KEY', {
  logger: {
    debug: console.log,
    info: console.log,
    error: console.error
  }
});

记录请求详情 #

javascript
async function debugSearch(query, params) {
  console.log('Search request:', {
    query,
    params,
    timestamp: new Date().toISOString()
  });
  
  const start = Date.now();
  
  try {
    const results = await index.search(query, params);
    
    console.log('Search response:', {
      nbHits: results.nbHits,
      processingTimeMS: results.processingTimeMS,
      duration: Date.now() - start
    });
    
    return results;
  } catch (error) {
    console.error('Search error:', {
      status: error.status,
      message: error.message,
      duration: Date.now() - start
    });
    
    throw error;
  }
}

使用getRankingInfo #

javascript
const results = await index.search('iphone', {
  getRankingInfo: true
});

results.hits.forEach(hit => {
  console.log(hit.name, hit._rankingInfo);
});

错误监控 #

集成错误追踪 #

javascript
async function monitoredSearch(query) {
  try {
    return await index.search(query);
  } catch (error) {
    // 发送到错误追踪服务
    trackError({
      type: 'algolia_search_error',
      query,
      status: error.status,
      message: error.message
    });
    
    throw error;
  }
}

错误统计 #

javascript
const errorStats = {
  total: 0,
  byStatus: {}
};

function recordError(error) {
  errorStats.total++;
  errorStats.byStatus[error.status] = 
    (errorStats.byStatus[error.status] || 0) + 1;
}

function getErrorStats() {
  return errorStats;
}

常见问题解决 #

索引不存在 #

javascript
// 检查索引是否存在
async function ensureIndex(indexName) {
  try {
    await client.initIndex(indexName).getSettings();
  } catch (error) {
    if (error.status === 404) {
      // 创建索引
      await client.initIndex(indexName).setSettings({});
    }
  }
}

API密钥无效 #

javascript
// 验证API密钥
async function validateApiKey() {
  try {
    await client.listIndices();
    return true;
  } catch (error) {
    if (error.status === 401 || error.status === 403) {
      return false;
    }
    throw error;
  }
}

请求超时 #

javascript
// 设置超时
const client = algoliasearch('APP_ID', 'API_KEY', {
  requestOptions: {
    timeout: 5000  // 5秒超时
  }
});

总结 #

错误处理要点:

要点 说明
状态码 按状态码分类处理
重试 指数退避重试机制
降级 缓存、默认数据
提示 用户友好的错误信息
调试 日志、getRankingInfo
监控 错误追踪、统计

恭喜你完成了Algolia文档的学习!

最后更新:2026-03-28