在筛选操作中使用async / await,在第一次等待调用后不等待完成

赛百斯

对于特定功能,需要数据库中的标签(RFID)列表,但应检查各种表。

该问题集中在长期运行的问题上,该问题await在继续进行下一个之前就没有完成。

问题:

下面调用的代码按如下方式运行(#数字与下面代码中的数字相对应):

  1. getAllTags() 被调用,启动过程
  2. await db.dbRfid.findAll()返回有效数量为X的有效结果(不是Promise对象)
  3. 开始过滤对有效对象的调用并等待完成(等待地点,因为内部的某些函数调用是异步调用。
  4. 呼叫 const driverTags = await tag.getDrivers();

在这一点上,希望该函数返回结果并继续执行下一个函数,即

// #5
const truckTags = await tag.getTrucks();

实际上发生的是每个allTags项目,getDrivers()被调用和filter()退出,并且代码继续执行下一个步骤:

// #6
if (pureTags) {
    return filteredTags;
}

题:

据我了解,我await荷兰国际集团async正常运作,但它似乎像过滤器仅接受/允许一个async操作。

我以为我做错了什么,但我无法确定问题的原因。任何意见,将不胜感激!

完整的代码实现如下:

用例如调用

const listOfTags = await getAllTags();

特定标签要求(所有有效,未使用,已启用和已撤销的标签)

const listOfTags = await getAllTags(false, true, true, true);

问题代码:

// #1
const getAllTags = async (pureTags = false, unused = true, enabled = true, notRevoked = false) => {
    // #2
    let allTags = await db.dbRfid.findAll()
    // #3
    let filteredTags = await allTags.filter(async tag => {
        // check tag used
        if (unused) {
            // #4
            const driverTags = await tag.getDrivers();
            // #5
            const truckTags = await tag.getTrucks();
            const userTags = await tag.getUsers();
            if (driverTags.length > 0) {
                return false;
            }
            if (truckTags.length > 0) {
                return false;
            }
            if (userTags.length > 0) {
                return false;
            }
        }

        // check tag enabled
        if (enabled && !tag.enabled) {
            return false;
        }

        // check tag revoked or return true
        return notRevoked && !tag.revoked;
    });

    // return tags as is
    // #6
    if (pureTags) {
        return filteredTags;
    }

    return filteredTags.map(tag => {
        return {
            id: tag.id,
            rfid: tag.rfid,
            expiryDate: tag.expiryDate,
            revoked: tag.revoked,
            enabled: tag.enabled
        }
    });
}

更新资料

我应该提一下:

  1. 没有显示出任何类型的“错误”来指示某些问题。
  2. .getDrivers()是由sequelize创建的吸气剂,该吸气剂返回承诺。

更新2

经过评论 evgeni fotia

我最初有这段代码,但是选择不包含它,因为它可能会处理一些复杂的事情。但是,这是我尝试添加的原始代码await Promise.all()

const getAllTags = async (pureTags = false, unused = true, enabled = true, notRevoked = false) => {
    let allTags = await db.dbRfid.findAll()
    let filteredTags = await Promise.all(
        // await allTags.filter(async tag => {      //tried the await here too - for good measure
        allTags.filter(async tag => {
            // check tag used
            if (unused) {
                const driverTags = await tag.getDrivers();
                const truckTags = await tag.getTrucks();
                const userTags = await tag.getUsers();
                if (driverTags.length > 0) {
                    return false;
                }
                if (truckTags.length > 0) {
                    return false;
                }
                if (userTags.length > 0) {
                    return false;
                }
            }

            // check tag enabled
            if (enabled && !tag.enabled) {
                return false;
            }

            // check tag revoked or return true
            return notRevoked && !tag.revoked;
        })
    );

    // return tags as is
    if (pureTags) {
        return filteredTags;
    }

    return filteredTags.map(tag => {
        return {
            id: tag.id,
            rfid: tag.rfid,
            expiryDate: tag.expiryDate,
            revoked: tag.revoked,
            enabled: tag.enabled
        }
    });
}

请注意,在此更新中或原始问题中运行代码后,我看到调试器点击了该getDrivers()方法,然后将(HTTP)响应发送到客户端,并且仅在0.5〜1s之后,我看到该getDrivers()方法返回并继续执行下一个方法。

托玛拉克

正如TJ Chowder所评论的那样,您的中心问题是,您正在尝试的.filter()东西有时是布尔值,有时是诺言。

您应该以不同的步骤进行映射和过滤。我倾向于使用.then()语法,因此这是我的方法:

const getAllTags = (pureTags = false, unused = true, enabled = true, notRevoked = false) => {
    return db.dbRfid.findAll()
        .then(allTags => allTags.map(tag => Promise.resolve(
            enabled === tag.enabled && notRevoked === !tag.revoked && Promise.all([
                tag.getDrivers(), tag.getTrucks(), tag.getUsers()
            ]).then(results => results.some(r => r.length))
        ).then(ok => ok ? tag : null)))
        .then(pendingTags => Promise.all(pendingTags))
        .then(resolvedTags => resolvedTags.filter(tag => tag))
        .then(filteredTags => filteredTags.map(tag => pureTags ? tag : {
            id: tag.id,
            rfid: tag.rfid,
            expiryDate: tag.expiryDate,
            revoked: tag.revoked,
            enabled: tag.enabled
        }));
};

此代码的逻辑:

  • 从数据库产生的标签中获取标签,即对标签数组的承诺
    Promise<Tag[]>
  • 将每个标签映射到一个新的Promise,该Promise可以解析为标签本身,或者null根据我们发现使用的条件Promise.resolve()来解决该检查产生的潜在(*)异步性质
    Promise<Promise<Tag|null>[]>
  • 等待所有那些内在的承诺用农产品解决Promise.all()
    <Promise<(Tag|null)[]>
  • 筛选出null的值(即标签,我们不希望)
    产生<Promise<Tag[]>
  • 将标签映射到所需的整体结果数据结构,具体取决于pureTags
    产品<Promise<(Tag|object)[]>

(*)Promise.all(),如果前提条件检查时才会激活,因短路。如果不是,则只是一个立即Promise.resolve(false)解析为的false在另一种情况下,它将与Promise.resolve(<Promise<Boolean>)完全相同Promise.resolve(Boolean)这样我们可以统一同步测试和异步测试。

在随后的步骤中,.then()我们可以决定是否返回tag-或null,以指示此标记未通过过滤条件。null随后的值由挑选出来resolvedTags.filter(tag => tag)

请注意,您的代码序列化三个异步检查(getDriversgetTrucksgetUsers),因为下开始之前,每个等待。使用Promise.all()让它们并行运行,这是我不喜欢async/await进行一切操作的原因之一

我将其重写为async/ awaitstyle作为练习。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

第一次调用后如何对函数进行反跳操作?

来自分类Dev

使用对象作为查找表:第一次调用后值不会更新

来自分类Dev

如果我只是使用wait()一次等待一个孩子完成,我是否需要对SIGCHLD处理程序做任何事情?

来自分类Dev

NSURLConnection不调用方法(第一次使用)

来自分类Dev

NSURLConnection不调用方法(第一次使用)

来自分类Dev

Swift:第一次使用后隐藏View Controller

来自分类Dev

为什么在使用 node 和 redis 时我的承诺没有解决?我的数组返回第一次迭代而不是等待整个代码运行

来自分类Dev

第一次使用Mockito

来自分类Dev

Laravel - 第一次使用

来自分类Dev

html界面在第一次使用后消失,并向我抛出一些错误

来自分类Dev

Python,“如果第一次调用line,则执行其他操作”

来自分类Dev

Swift viewWillAppear第一次没有使用TabBarController调用

来自分类Dev

在地图中使用多次等待

来自分类Dev

realloc()在第一次调用后未分配

来自分类Dev

第一次进入App时,使用UIPageViewController快速完成教程页面的首选方法是

来自分类Dev

jQuery函数仅在第一次按下提交按钮时调用控制器操作

来自分类Dev

使用setInterval第一次出现

来自分类Dev

使用jquery / javascript防止第一次警报

来自分类Dev

仅第一次使用ListView项

来自分类Dev

第一次错误使用Picasso加载图片

来自分类Dev

第一次如何使用eclipse设置SQLite?

来自分类Dev

使用SharpSVN找到线的第一次出现?

来自分类Dev

第一次使用MongoTemplate保存文档

来自分类Dev

$()。html()仅在第一次使用

来自分类Dev

第一次使用按钮代码

来自分类Dev

第一次输入时如何使用变量

来自分类Dev

@keyframes动画只能在第一次使用

来自分类Dev

jQuery .on()仅在第一次使用

来自分类Dev

使用setInterval第一次出现

Related 相关文章

  1. 1

    第一次调用后如何对函数进行反跳操作?

  2. 2

    使用对象作为查找表:第一次调用后值不会更新

  3. 3

    如果我只是使用wait()一次等待一个孩子完成,我是否需要对SIGCHLD处理程序做任何事情?

  4. 4

    NSURLConnection不调用方法(第一次使用)

  5. 5

    NSURLConnection不调用方法(第一次使用)

  6. 6

    Swift:第一次使用后隐藏View Controller

  7. 7

    为什么在使用 node 和 redis 时我的承诺没有解决?我的数组返回第一次迭代而不是等待整个代码运行

  8. 8

    第一次使用Mockito

  9. 9

    Laravel - 第一次使用

  10. 10

    html界面在第一次使用后消失,并向我抛出一些错误

  11. 11

    Python,“如果第一次调用line,则执行其他操作”

  12. 12

    Swift viewWillAppear第一次没有使用TabBarController调用

  13. 13

    在地图中使用多次等待

  14. 14

    realloc()在第一次调用后未分配

  15. 15

    第一次进入App时,使用UIPageViewController快速完成教程页面的首选方法是

  16. 16

    jQuery函数仅在第一次按下提交按钮时调用控制器操作

  17. 17

    使用setInterval第一次出现

  18. 18

    使用jquery / javascript防止第一次警报

  19. 19

    仅第一次使用ListView项

  20. 20

    第一次错误使用Picasso加载图片

  21. 21

    第一次如何使用eclipse设置SQLite?

  22. 22

    使用SharpSVN找到线的第一次出现?

  23. 23

    第一次使用MongoTemplate保存文档

  24. 24

    $()。html()仅在第一次使用

  25. 25

    第一次使用按钮代码

  26. 26

    第一次输入时如何使用变量

  27. 27

    @keyframes动画只能在第一次使用

  28. 28

    jQuery .on()仅在第一次使用

  29. 29

    使用setInterval第一次出现

热门标签

归档