如何让Javascript等待Promise完成后再发送后续请求
问题核心原因
- async 函数执行后默认返回Promise对象,你在构造函数中直接将
getServicesList的返回值赋值给state.servicesList,实际存的是Promise实例,而非接口返回的服务列表数据,所以第二个请求发给后端的参数里servicesPromise对应的值是不可被后端正常解析的Promise对象,自然只能收到前面的普通参数。 - async/await是Promise的语法糖,并不会改变异步执行的本质,你必须等待Promise状态变为resolve之后才能拿到真实的返回数据。
修复步骤
1. 调整state初始化与第一个接口的调用时机
构造函数是同步执行的,无法等待异步接口返回结果,先将servicesList初始化为空值,在组件挂载后再调用第一个接口,拿到结果后更新state:
constructor(props) { super(props); this.ongoingRequestId = undefined; this.ongoingRequests = new Map(); this.state = { servicesList: [] // 初始化为空数组,不要直接赋值异步方法返回的Promise } } // 组件挂载后调用第一个接口 componentDidMount = async () => { const instanceIds = this.getInstanceIds(); const servicesList = await this.getServicesList(instanceIds); this.setState({ servicesList }); }
2. 调整第二个请求的逻辑,等待第一个接口返回后再发请求
修改searchLogs为异步方法,确保拿到真实的servicesList之后再构建请求参数:
searchLogs = async (size, page, status, callback) => { loadingService.showLoadingModal("loadingLogsPage", this.props.location.pathname); // 等待servicesList的异步结果返回,若已经请求完成会直接拿到值 const realServicesList = await this.state.servicesList; // 构建请求参数时传入真实的服务列表 const searchObject = this.buildSearchObject(size, page, status, realServicesList); ElasticSearchApi.search(searchObject, this.props.token) .then(response => { callback(response); }) .catch((error) => { loadingService.hideLoadingModal("loadingLogsPage", this.props.location.pathname); Toastr.error(ResponseErrorProvider.getError(error)); if (ResponseErrorProvider.isUnauthorized(error)) { Toastr.error(error.response.data.message); this.props.onLogout(); } }); };
3. 调整buildSearchObject方法,接收真实的服务列表作为参数
buildSearchObject = (size, page, status, servicesList) => { let interval = TimestampUtils.getInterval(this.props.logsTimeInterval); let from = interval.from * 1000; let to = interval.to * 1000; return { fromMillis: from, toMillis: to, size: size, page: page, salesline: this.props.salesline, environment: this.props.environment, routes: this.props.routes, sources: this.props.sources, targets: this.props.targets, customFilters: [...this.props.filters.values(), ...this.getEnabledAdvancedFilters().values()], status: status === LogStatus.ALL ? "" : status, sortFieldName: this.props.sortColumn, order: this.props.sortOrder, searchFilter: this.props.searchFilter, searchFilterOperator: this.props.searchFilterOperator, applications: this.props.applications, openedStores: this.props.openedStores, services: servicesList // 替换原来的Promise,传入真实的服务列表数据 } };
查看完整请求内容的方法
在调用ElasticSearchApi.search的前一行添加代码console.log('完整请求参数:', searchObject),打开浏览器控制台即可看到打印的完整参数;也可以切换到控制台的「网络」面板,找到对应的接口请求,查看「请求载荷」板块,就能看到实际发送给后端的所有内容。
内容的提问来源于stack exchange,提问作者Bogdan Anton
相关产品推荐
相关产品推荐

