Skip to content

API调用问题

本页面收集了使用uni-app开发过程中常见的API调用相关问题及解决方案。

目录

API调用基础问题

Q1: 如何正确引入和使用uni-app的API?

问题描述:初学者常常不清楚如何正确引入和使用uni-app提供的API。

解决方案:uni-app的API是全局对象,可以直接在代码中使用,无需导入。

js
// 正确使用方式 - 直接调用
uni.showToast({
  title: '操作成功',
  icon: 'success'
});

// 错误使用方式 - 不需要导入
import uni from 'uni-app'; // 错误,不需要这样导入

Q2: API返回的Promise如何正确处理?

问题描述:很多开发者不清楚uni-app API的Promise用法。

解决方案:大多数uni-app API支持Promise风格调用,可以使用async/await或then/catch处理。

js
// 方式一:使用async/await
async function getUserInfo() {
  try {
    const res = await uni.getUserProfile({
      desc: '用于完善用户资料'
    });
    console.log(res.userInfo);
  } catch (e) {
    console.error(e);
  }
}

// 方式二:使用then/catch
uni.getUserProfile({
  desc: '用于完善用户资料'
})
.then(res => {
  console.log(res.userInfo);
})
.catch(err => {
  console.error(err);
});

网络API问题

Q3: uni.request请求失败或超时怎么办?

问题描述:使用uni.request发起网络请求时遇到失败或超时问题。

解决方案

  1. 检查网络连接和服务器状态
  2. 设置合理的超时时间
  3. 添加重试机制
  4. 确保请求URL的协议正确(https/http)
  5. 检查是否有跨域问题
js
// 带重试机制的请求示例
function requestWithRetry(options, maxRetries = 3) {
  return new Promise((resolve, reject) => {
    let retryCount = 0;
    
    function attempt() {
      uni.request({
        ...options,
        success: (res) => {
          resolve(res);
        },
        fail: (err) => {
          retryCount++;
          if (retryCount <= maxRetries) {
            console.log(`请求失败,第${retryCount}次重试`);
            setTimeout(() => {
              attempt();
            }, 1000 * retryCount); // 递增重试延迟
          } else {
            reject(err);
          }
        }
      });
    }
    
    attempt();
  });
}

Q4: 小程序环境下API请求域名限制问题

问题描述:在小程序环境中,API请求域名必须在小程序管理后台配置,否则请求会失败。

解决方案

  1. 在小程序管理后台的"开发设置"中添加服务器域名
  2. 开发阶段可以在开发工具中勾选"不校验合法域名"选项
  3. 使用小程序云开发避免域名限制
js
// 根据环境判断是否需要使用完整域名
const BASE_URL = process.env.NODE_ENV === 'development' 
  ? '/api' 
  : 'https://api.example.com';

uni.request({
  url: `${BASE_URL}/user/info`,
  // 其他配置...
});

存储API问题

Q5: uni.setStorage和uni.setStorageSync有什么区别?

问题描述:开发者常常不清楚同步和异步存储API的区别和使用场景。

解决方案

  • uni.setStorage是异步API,不会阻塞主线程,适合存储大量数据
  • uni.setStorageSync是同步API,会阻塞主线程,适合存储少量关键数据
js
// 异步存储 - 推荐用法
uni.setStorage({
  key: 'userInfo',
  data: userInfo,
  success: function() {
    console.log('存储成功');
  }
});

// 同步存储 - 少量数据时使用
try {
  uni.setStorageSync('token', token);
} catch (e) {
  console.error(e);
}

Q6: 存储空间限制问题

问题描述:小程序环境下存储空间有限制(一般为10MB),超出限制会导致存储失败。

解决方案

  1. 只存储必要的数据
  2. 大文件使用云存储
  3. 定期清理不必要的缓存数据
  4. 实现存储空间管理机制
js
// 存储空间管理示例
function safeStorage(key, data) {
  try {
    // 先尝试存储
    uni.setStorageSync(key, data);
  } catch (e) {
    // 如果失败,清理部分旧数据后再尝试
    const keys = uni.getStorageInfoSync().keys;
    // 按时间排序,清理最早的数据
    const oldKeys = keys.filter(k => k.startsWith('cache_')).sort();
    if (oldKeys.length > 0) {
      uni.removeStorageSync(oldKeys[0]);
      // 重试存储
      uni.setStorageSync(key, data);
    }
  }
}

位置和地图API问题

Q7: 获取位置信息失败

问题描述:调用uni.getLocation API获取用户位置信息失败。

解决方案

  1. 确保已在manifest.json中配置了地理位置权限
  2. 检查用户是否授权了位置权限
  3. 在真机上测试,模拟器可能无法正常获取位置
  4. 考虑位置服务是否开启
js
// 获取位置前先检查权限
uni.getSetting({
  success: (res) => {
    if (!res.authSetting['scope.userLocation']) {
      uni.authorize({
        scope: 'scope.userLocation',
        success: () => {
          getLocation();
        },
        fail: () => {
          uni.showModal({
            title: '提示',
            content: '需要获取您的地理位置,请确认授权',
            success: (res) => {
              if (res.confirm) {
                uni.openSetting();
              }
            }
          });
        }
      });
    } else {
      getLocation();
    }
  }
});

function getLocation() {
  uni.getLocation({
    type: 'gcj02',
    success: (res) => {
      const { latitude, longitude } = res;
      console.log(`当前位置:${latitude}, ${longitude}`);
    },
    fail: (err) => {
      console.error('获取位置失败', err);
    }
  });
}

文件API问题

Q8: 文件上传失败问题

问题描述:使用uni.uploadFile上传文件时失败。

解决方案

  1. 检查文件路径是否正确
  2. 确认服务器端是否正确配置了文件上传接口
  3. 检查文件大小是否超出限制
  4. 确保网络连接稳定
  5. 添加上传进度监控和重试机制
js
// 带进度监控和重试的文件上传
function uploadFileWithRetry(options, maxRetries = 3) {
  return new Promise((resolve, reject) => {
    let retryCount = 0;
    
    function attempt() {
      const uploadTask = uni.uploadFile({
        ...options,
        success: (res) => {
          resolve(res);
        },
        fail: (err) => {
          retryCount++;
          if (retryCount <= maxRetries) {
            console.log(`上传失败,第${retryCount}次重试`);
            setTimeout(() => {
              attempt();
            }, 1000 * retryCount);
          } else {
            reject(err);
          }
        }
      });
      
      uploadTask.onProgressUpdate((res) => {
        console.log('上传进度', res.progress);
        if (options.onProgress) {
          options.onProgress(res.progress);
        }
      });
    }
    
    attempt();
  });
}

// 使用示例
uploadFileWithRetry({
  url: 'https://api.example.com/upload',
  filePath: tempFilePath,
  name: 'file',
  onProgress: (progress) => {
    this.uploadProgress = progress;
  }
}).then(res => {
  console.log('上传成功', res);
}).catch(err => {
  console.error('上传失败', err);
});

界面API问题

Q9: uni.showToast和uni.showModal使用时机

问题描述:开发者常常不清楚何时使用toast,何时使用modal。

解决方案

  • uni.showToast:用于简短的操作结果反馈,自动消失
  • uni.showModal:用于需要用户确认或选择的场景,不会自动消失
js
// 操作成功反馈 - 使用Toast
uni.showToast({
  title: '保存成功',
  icon: 'success',
  duration: 2000
});

// 需要用户确认的场景 - 使用Modal
uni.showModal({
  title: '提示',
  content: '是否确认删除该条记录?',
  success: (res) => {
    if (res.confirm) {
      deleteRecord();
    }
  }
});

Q10: 页面导航API使用问题

问题描述:uni.navigateTo、uni.redirectTo、uni.switchTab等导航API使用混淆。

解决方案

  • uni.navigateTo:保留当前页面,跳转到应用内的某个页面
  • uni.redirectTo:关闭当前页面,跳转到应用内的某个页面
  • uni.switchTab:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
  • uni.navigateBack:关闭当前页面,返回上一页面或多级页面
  • uni.reLaunch:关闭所有页面,打开到应用内的某个页面
js
// 正确使用导航API
// 1. 普通页面跳转,保留当前页面
uni.navigateTo({
  url: '/pages/detail/detail?id=1'
});

// 2. 替换当前页面
uni.redirectTo({
  url: '/pages/result/result?status=success'
});

// 3. 跳转到tabBar页面
uni.switchTab({
  url: '/pages/home/home'
});

// 4. 返回上一页
uni.navigateBack({
  delta: 1
});

// 5. 重启到某个页面
uni.reLaunch({
  url: '/pages/login/login'
});

平台差异API问题

Q11: 如何处理不同平台特有的API?

问题描述:某些API只在特定平台可用,直接调用会导致在其他平台报错。

解决方案:使用条件编译或运行时平台判断。

js
// 方法1:使用条件编译
// #ifdef MP-WEIXIN
wx.requestSubscribeMessage({
  tmplIds: ['xxx'],
  success: (res) => {
    console.log('订阅消息成功');
  }
});
// #endif

// 方法2:运行时判断
if (uni.getSystemInfoSync().platform === 'android') {
  // 仅安卓平台执行的代码
  console.log('当前是安卓平台');
}

// 方法3:封装跨平台API
function shareContent(options) {
  // #ifdef MP-WEIXIN
  wx.shareAppMessage(options);
  // #endif
  
  // #ifdef APP-PLUS
  uni.share({
    provider: 'weixin',
    ...options
  });
  // #endif
  
  // #ifdef H5
  // H5环境下的分享逻辑
  // #endif
}

Q12: 如何优雅地处理API的平台兼容性?

问题描述:不同平台的API参数和行为可能有差异,导致兼容性问题。

解决方案:创建平台适配层,统一API调用接口。

js
// 创建API适配层示例
const api = {
  // 统一的文件选择API
  chooseFile: function(options = {}) {
    // #ifdef APP-PLUS || H5
    return uni.chooseFile({
      count: options.count || 1,
      extension: options.extension || [],
      ...options
    });
    // #endif
    
    // #ifdef MP
    return uni.chooseMessageFile({
      count: options.count || 1,
      type: options.type || 'all',
      ...options
    });
    // #endif
  },
  
  // 统一的分享API
  share: function(options = {}) {
    return new Promise((resolve, reject) => {
      // #ifdef APP-PLUS
      uni.share({
        provider: options.provider || 'weixin',
        scene: options.scene || 'WXSceneSession',
        type: options.type || 0,
        title: options.title,
        summary: options.summary || options.desc,
        imageUrl: options.imageUrl,
        href: options.link,
        success: resolve,
        fail: reject
      });
      // #endif
      
      // #ifdef MP-WEIXIN
      wx.showShareMenu({
        withShareTicket: true,
        menus: ['shareAppMessage', 'shareTimeline'],
        success: resolve,
        fail: reject
      });
      // #endif
      
      // #ifdef H5
      // H5环境实现分享
      if (navigator.share && options.type === 'system') {
        navigator.share({
          title: options.title,
          text: options.summary || options.desc,
          url: options.link
        }).then(resolve).catch(reject);
      } else {
        // 使用自定义分享UI
        uni.showModal({
          title: '分享提示',
          content: '请点击浏览器自带的分享按钮进行分享',
          showCancel: false,
          success: resolve,
          fail: reject
        });
      }
      // #endif
    });
  }
};

// 使用示例
api.chooseFile({
  count: 3,
  success: (res) => {
    console.log('选择的文件', res.tempFiles);
  }
});

总结

在使用uni-app API时,需要注意以下几点:

  1. 了解API特性:同步/异步、返回值、参数要求等
  2. 处理平台差异:使用条件编译或运行时判断
  3. 错误处理:添加try/catch或fail回调处理异常情况
  4. 权限管理:注意API可能需要的权限申请
  5. 性能优化:合理使用API,避免频繁调用影响性能

如果您遇到本文未涵盖的API问题,可以查阅uni-app官方API文档或在社区中寻求帮助。

一次开发,多端部署 - 让跨平台开发更简单