快速响应,具有递归功能

问题描述

我正试图从Cloudinary中获取所有照片,但是每次调用限制为500个元素。

呼叫中存在一个名为next_cursor的属性,您可以将其用作分页。

我以递归方式进行操作,但是当我尝试在Express中发送响应超出范围时,关于如何使用递归函数的结果进行响应的任何想法?

谢谢!

const express = require("express");
const router = express.Router();
const cloudinary = require("cloudinary").v2;

const { cloudinarySettings } = require("../config/cloudinary_config");

router.get("/statistics",async (req,res) => {
    function list_resources(results,next_cursor = null) {
        cloudinary.api.resources(
            {
                resource_type: "image",mex_results: 500,next_cursor: next_cursor,},function (err,res) {
                console.log(err);
                res.resources.forEach(function (resource) {
                    results.push(resource);
                });

                if (res.next_cursor) {
                    list_resources(results,res.next_cursor);
                } else {
                    return res.status(200).json(results)
                }
            }
        );
    }

    const results = [];
    list_resources(results);
});

解决方法

您将需要修改list_resources函数以按如下方式返回promise,然后使用async-await等待结果,然后再提交res

router.get("/statistics",async (req,res) => {
    async function list_resources(results,next_cursor = null) {
        await new Promise((resolve) => {
            cloudinary.api.resources(
                {
                    resource_type: "image",mex_results: 500,next_cursor: next_cursor,},function (err,res) {
                    if (err) {
                        console.log(err);
                        resolve();
                        
                    } else {
                        res.resources.forEach(function (resource) {
                            results.push(resource);
                        });

                        if (res.next_cursor) {
                            list_resources(results,res.next_cursor).then(() => resolve());
                        } else {
                            resolve();
                        }
                    }
                    
                }
            );
        });
    }

    const results = [];
    await list_resources(results);
    return res.status(200).json(results);
});
,

我可能会以不同的方式分解问题,并制作一个更简单的递归函数来返回结果,而不是修改传入的数组。为了保持整洁,我还将函数移出router.get回调。 / p>

所以它可能看起来像这样:

const listResources = async ({resource_type,max_results = 500,next_cursor = null} = {}) => {
  return new Promise((resolve,reject) => {
    cloudinary .api .resources (
      {resource_type,max_results,next_cursor},async (err,{resources,next_cursor}) => {
        try {
          if (err) {reject (err)}
          else resolve ([
            ...resources,...(next_cursor ? await listResources ({resource_type,next_cursor}) : [])
          ])
        } catch (err) {reject (err)}
      }
    )
  })
}

router.get('/statistics',res) => {
  try {
    const results = await listResources ({resource_type: 'image'})
    res .status (200) .json (results)
  } catch (err) {
    console .warn (err)
    res .status (404) // or 500,or whatever,based on error
  }
})

最有趣的部分是:

    resolve ([
      ...resources,next_cursor}) : [])
    ])

如果返回一个next_cursor值,则在解析之前,将使用它的递归调用结果附加到当前结果中。如果没有得到,则附加一个空数组。

很高兴能够编写这个可以说更简单的cloudinary回调函数:

    async (err,next_cursor}) => err 
      ? reject (err)
      : resolve ([
          ...resources,next_cursor}) : [])
        ])

避免使用try-catchif-else块。但是我找不到一种简单的方法来将错误传递回最初调用listResources的函数。

您可以在浏览器中使用此代码段中cloudinaryrouter的虚拟实现对此进行测试:

const listResources = async ({resource_type,next_cursor = null}) => {
  return new Promise((resolve,reject) => {
    cloudinary.api.resources(
      {resource_type,res) => {
  try {
    const results = await listResources ({resource_type: 'image',max_results: 3})
    res .status (200) .json (results)
  } catch (err) {
    console .warn (err)
    res .status (500) // or whatever,based on error
  }
})
.as-console-wrapper {max-height: 100% !important; top: 0}
<script>
// Dummy implementations for testing:

const cloudinary = (() => {
  const vals = [{t: 'image',id: 1,v: 'a'},{t: 'image',id: 2,v: 'b'},id: 3,v: 'c'},{t: 'pdf',id: 4,v: 'd'},id: 5,v: 'e'},id: 6,v: 'f'},{t: 'video',id: 7,v: 'g'},id: 8,v: 'h'},id: 9,v: 'i'},id: 10,v: 'j'},id: 11,v: 'k'},id: 12,v: 'l'}]; 
  const last = (xs) => xs.length ? xs[xs.length - 1] : undefined; 
  return {api: {
    resources: ({resource_type,next_cursor = 0},fn) => {
      const res = vals .filter (({t,id}) => t == resource_type && id > next_cursor).slice(0,max_results)
//      fn (next_cursor == 3 ? 'houston,we have a problem' : null,{  // *** use to test an error condition ***
      fn (null,{
        resources: res,...(res.length > 0 && last(res).id < last(vals).id ? {next_cursor: last(res).id} : {})
      })
    }
  }}
})()

const router = {
  get: (path,fn) =>
    fn (
      {},{status: (n) => {
        console.log(`returning ${n} for request to ${path}`)
        return {
          json: val => console.log(`Body: \n${JSON.stringify(val,null,4)}`)
        }
      }}
    )
}
</script>

如果您取消注释虚拟虚拟代码中的替代行并注释了上一行,则可以看到cloudinary .api .resources引发错误时的行为。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...