redux 在React和JavaScript中返回数据时出现异步问题[duplicate]

fumotvh3  于 2022-11-12  发布在  React
关注(0)|答案(1)|浏览(123)

此问题在此处已有答案

How can I access the value of a promise?(共14个答案)
How do I return the response from an asynchronous call?(44个答案)
两个月前关门了。
我需要返回getThumbnail函数来调整图片的大小。现在的问题是当我尝试下面的代码时,所有分配给dispatch的有效负载现在都返回一个promise。我如何摆脱这个问题,只返回一个普通的有效负载。以前我没有getThumbnail也可以返回它,但现在我被迫返回它,因为getThumbnail是一个promise。我如何修复这个问题?我应该调整getThumbnail函数还是?
关于这个问题的代码:

const responseImages = response?.data?.map(async (image) => {
                return {
                    productName: image?.uploadResult?.productTitle,
                    imageFile: await getThumbnail(
                        images.find((img) => img?.imageFileName === image?.mediaCode)
                        ?.imageFile || null, {
                            thumbWidth: 100,
                            thumbHeight: 100,
                            bgColor: "black",
                        }
                    ),
                    imageFileName: image?.mediaCode || "",
                };
            });

助手.js

const loadImage = (src) =>
  new Promise((resolve, reject) => {
    const img = new Image()
    img.onload = () => resolve(img)
    img.onerror = reject
    img.src = src
  })

const resize = (imageWidth, imageHeight, thumbWidth, thumbHeight) => {
  let w = 0,
    h = 0,
    x = 0,
    y = 0,
    widthratio = imageWidth / thumbWidth,
    heightratio = imageHeight / thumbHeight,
    maxratio = Math.max(widthratio, heightratio)
  if (maxratio > 1) {
    w = imageWidth / maxratio
    h = imageHeight / maxratio
  } else {
    w = imageWidth
    h = imageHeight
  }
  x = (thumbWidth - w) / 2
  y = (thumbHeight - h) / 2
  return { w: w, h: h, x: x, y: y }
}

export async function getThumbnail(
  photo,
  { thumbWidth, thumbHeight, bgColor }
) {
  const img = await loadImage(URL.createObjectURL(photo))
  const { naturalWidth, naturalHeight } = img

  const canvas = document.createElement('canvas')
  const cx = canvas.getContext('2d')

  canvas.width = thumbWidth
  canvas.height = thumbHeight

  const dimensions = resize(
    naturalWidth,
    naturalHeight,
    thumbWidth,
    thumbHeight
  )

  cx.fillStyle = bgColor
  cx.fillRect(0, 0, thumbWidth, thumbHeight)

  cx.drawImage(img, dimensions.x, dimensions.y, dimensions.w, dimensions.h)

  return canvas.toDataURL('image/jpeg')
}

操作.js

export const uploadPhotos =
    ({
        photos,
        size,
        controller
    }) =>
    async (dispatch) => {
        // Identify the part of the file name that excludes the (optional) sequence number
        const keyedphotos = photos.map((photo) => [
            photo.imageFileName.replace(/-\w+\.\w+$/, ""),
            photo,
        ]);
        // Create a group for each such prefix
        const map = new Map(keyedphotos.map(([key]) => [key, []]));
        // Populate those groups
        for (const [key, photo] of keyedphotos) map.get(key).push(photo);
        // And extract those groups into an array (of subarrays)
        const photoGroups = [...map.values()];
        let index = 0; // Keep the index counter separate

        photoGroups.forEach(async (photos) => {
            // Iterate the groups that can run in parallel
            for (const photo of photos) {
                // Iterate the photos that should run sequentially
                const id = index++; // Get the next unique id
                const formData = new FormData();
                formData.append(photo?.imageFileName, photo?.imageFile);

                dispatch({
                    type: constants.UPLOAD_PHOTOS_START,
                    size
                });
                try {
                    const response = await axios.post(
                        `${API_URL}/photos/upload`,
                        formData, {
                            onUploadProgress({
                                loaded,
                                total
                            }) {
                                dispatch(setUploadProgress({
                                    id,
                                    loaded,
                                    total
                                })); // Use id
                            },
                            signal: controller.signal,
                        }
                    );

                    dispatch({
                        type: constants.UPLOAD_PHOTOS_SUCCESS,
                        payload: response.data,
                    });

                    const responseImages = response?.data?.map(async (image) => {
                        return {
                            productName: image?.uploadResult?.productTitle,
                            imageFile: await getThumbnail(
                                images.find((img) => img?.imageFileName === image?.mediaCode)
                                ?.imageFile || null, {
                                    thumbWidth: 100,
                                    thumbHeight: 100,
                                    bgColor: "black",
                                }
                            ),
                            imageFileName: image?.mediaCode || "",
                        };
                    });
                } catch (error) {
                    dispatch({
                        type: constants.UPLOAD_PHOTOS_FAILURE,
                        payload: error,
                    });
                }
            }
        });
    };
bvpmtnay

bvpmtnay1#

我假设您的response.data确实是一个数组,因此您可以使用map函数。
这里,问题福尔斯在您为map提供的函数上。
async...await函数实际上返回的是Promise,而不是已解析的对象。
因此,对于data中的每一项,您得到的是“解析数据的承诺,而不是数据本身”。
幸运的是,你只差一步就能实现你的愿望。
只需将代码封装到Promise.all()中,因为all(...)接受一个Promises数组,并返回解析后的数据。

const responseImages = await Promise.all(response?.data?.map(async (image) => {
                return {
                    productName: image?.uploadResult?.productTitle,
                    imageFile: await getThumbnail(
                        images.find((img) => img?.imageFileName === image?.mediaCode)
                        ?.imageFile || null, {
                            thumbWidth: 100,
                            thumbHeight: 100,
                            bgColor: "black",
                        }
                    ),
                    imageFileName: image?.mediaCode || "",
                };
            }));

最后,根据具体情况,您可以考虑Promise.allSettled()Promise.any()Promise.race()
阅读有关这些标准函数/方法的更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

相关问题