如何处理 Promise.all then 回调中的辅助等待用法

Han*_*ank 0 javascript promise async-await reactjs

我有两个调用来解析从 indexeddb 检索数据的承诺,如果无法加载数据,我希望它从 API 检索数据。

export const retrieveServiceRequest = createAsyncThunk(
  'csm/retrieveServiceRequest',
  async (
    retrievalPayload: any
  ) => {

    try {

      if (retrievalPayload.userId && retrievalPayload.serviceRequestTag) {
        const userServiceRequestKey: string = retrievalPayload.userId + '_' + retrievalPayload.serviceRequestTag;
        await Promise.all([
          csmIndexedDbService.getCSMData(CSM_Stores.CSM_SR_EDITED, userServiceRequestKey),
          csmIndexedDbService.getCSMData(CSM_Stores.CSM_SR_UNEDITED, userServiceRequestKey)
        ])
        .then (requestDataArray => {
          if (requestDataArray.length > 0 && requestDataArray[0]){
            return { serviceRequest: requestDataArray[0], serviceRequestOriginal: requestDataArray[1], isDirty: true, addToStore: true }
          } else {
            return await csmRequestDataService.getServiceRequest(retrievalPayload.serviceRequestId);
          }
        })
        .catch (error => 
          console.log(error)
        );
      }

    } catch (error) {
      console.log('Error: ', error);
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

我不确定的部分是:

return await csmRequestDataService.getServiceRequest(retrievalPayload.serviceRequestId);
Run Code Online (Sandbox Code Playgroud)

等待 API 时出现错误:

“await”表达式仅允许在异步函数内和模块的顶层使用

我应该如何处理第二轮的等待?

Tha*_*you 5

您可以使then处理程序异步,但最好不要混合两种样式。将 ed 表达式的结果分配await给一个变量,然后直接使用它,而不需要处理程序then

export const retrieveServiceRequest = createAsyncThunk(
  'csm/retrieveServiceRequest',
  async (
    retrievalPayload: any
  ) => {

    try {

      if (retrievalPayload.userId && retrievalPayload.serviceRequestTag) {
        const userServiceRequestKey: string = retrievalPayload.userId + '_' + retrievalPayload.serviceRequestTag;
        
        // assign to variable .
        const requestDataArray = await Promise.all([
          csmIndexedDbService.getCSMData(CSM_Stores.CSM_SR_EDITED, userServiceRequestKey),
          csmIndexedDbService.getCSMData(CSM_Stores.CSM_SR_UNEDITED, userServiceRequestKey)
        ])

        // move out of .then handler
        if (requestDataArray.length > 0 && requestDataArray[0]){
          return { serviceRequest: requestDataArray[0], serviceRequestOriginal: requestDataArray[1], isDirty: true, addToStore: true }
        } else {
          return await csmRequestDataService.getServiceRequest(retrievalPayload.serviceRequestId);
        }
      }
    } catch (error) {
      console.log('Error: ', error);
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

不要用try..catch和吞掉错误console.error,只需让它们冒出来 -

export const retrieveServiceRequest = createAsyncThunk(
  'csm/retrieveServiceRequest',
  async (
    retrievalPayload: any
  ) => {
     if (retrievalPayload.userId && retrievalPayload.serviceRequestTag) {
      const userServiceRequestKey: string = retrievalPayload.userId + '_' + retrievalPayload.serviceRequestTag;
      
      const requestDataArray = await Promise.all([
        csmIndexedDbService.getCSMData(CSM_Stores.CSM_SR_EDITED, userServiceRequestKey),
        csmIndexedDbService.getCSMData(CSM_Stores.CSM_SR_UNEDITED, userServiceRequestKey)
      ])

      if (requestDataArray.length > 0 && requestDataArray[0]){
        return { serviceRequest: requestDataArray[0], serviceRequestOriginal: requestDataArray[1], isDirty: true, addToStore: true }
      } else {
        return await csmRequestDataService.getServiceRequest(retrievalPayload.serviceRequestId);
      }
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

呼叫者可以随心所欲地处理它们 -

retrieveServiceRequest.catch(console.error)
Run Code Online (Sandbox Code Playgroud)

最后避免return-await ...反模式。所有async函数都隐式返回一个承诺 -

export const retrieveServiceRequest = createAsyncThunk(
  'csm/retrieveServiceRequest',
  async (
    retrievalPayload: any
  ) => {
     if (retrievalPayload.userId && retrievalPayload.serviceRequestTag) {
      const userServiceRequestKey: string = retrievalPayload.userId + '_' + retrievalPayload.serviceRequestTag;
      
      const requestDataArray = await Promise.all([
        csmIndexedDbService.getCSMData(CSM_Stores.CSM_SR_EDITED, userServiceRequestKey),
        csmIndexedDbService.getCSMData(CSM_Stores.CSM_SR_UNEDITED, userServiceRequestKey)
      ])

      if (requestDataArray.length > 0 && requestDataArray[0]){
        return { serviceRequest: requestDataArray[0], serviceRequestOriginal: requestDataArray[1], isDirty: true, addToStore: true }
      } else {
        // this does the exact same thing
        return csmRequestDataService.getServiceRequest(retrievalPayload.serviceRequestId);
      }
    }
  }
);
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助您了解该图案的优雅和简洁async..await。如果正确使用,它允许编写者在同步和异步控制流之间无缝且轻松地转换。