javascript - 异步困惑。处理 API 响应并失去对这段代码中发生的情况的理解

标签 javascript node.js asynchronous

我已经迷失在自己的头脑中,不知道如何最好地构造这个函数。 下面的代码大部分是正确的,我只是删除了底部的一些函数,并不重要。

应该发生什么:

  1. 我的 Node 应用程序在特定时间运行并调用 refreshDevices()
  2. 该函数从 API 获取 JSON 负载
  3. 该函数循环访问该负载中的元素并检查是否已有记录
  4. 如果没有记录则创建一条,如果有则更新
  5. 运行后,将创建一个日志条目,记录更改数量。

我的问题是日志条目发生在任何记录检查发生之前...我的日志显示 0 个添加和 0 个更新。 我尝试重写代码以使用内联异步/等待函数,但我认为这实际上与下面的相同。

我应该如何构造这个函数来完成我所说的事情。 我发现异步和同步的混合非常令人困惑。

  • 我什至尝试添加日志条目位以在 .finally() 中发生 block 在最后,但在检查发生之前执行。
  • 我已经使用 forEachmap 尝试过此操作。
refreshDevices(_timespan) {  
  const status = {
    added: 0,
    updated: 0,
  };

  // Standard API fetch & json() conversion
  fetch(`https://api.example.com/test&timespan=${timespan}`)
    .then((response) => response.json())
    .then((JSON) => {
      JSON.forEach((device) => {
        findDevice(device._id)
        .then(record => {
          if (!record) {
            addDeviceRecord(device);
            status.added++;
          } else {
            deviceSeen(device._id);
            status.updated++;
          }
        })
        .catch(error => {
          console.log('Error!');
        });
      });

      systemlog.log({
        message: 'Refresh',
        data: {
          success: true,
          note: `Added: ${status.added} & updated: ${status.updated}`,
        },
      });
    })
    .catch((error) => {
      systemlog.log({
        message: 'Refresh',
        type: systemlog.logType.ERROR,
        data: {
          success: false,
          note: error,
        },
      });
    });
}

function findDevice(id) {
  return DB('device').findOne({ id }); // this returns is a promise
}

function addDeviceRecord(record) {
  return DB('device').insertOne(record); // this returns is a promise
}

function deviceSeen(id) {
  return DB('device').updateOne({ id }, { $set: { lastSeen: new Date() } }); // this returns is a promise
}

这个问题

最佳答案

正如您所确定的,您的 system.log 调用在启动一连串尚未解决的 promise 后立即发生。

refreshDevices(_timespan) 函数中添加一个空数组,以在 forEach 中添加每个新的 Promise。

然后修改你的代码

JSON.forEach((device) => {
            promises.push( // Add this promise to the array
                findDevice(device._id)
                .then(record => {
                    if (!record) {
                        addDeviceRecord(device);
                        status.added++;
                    } else {
                        deviceSeen(device._id);
                        status.updated++;
                    }
                })
                .catch(error => {
                    console.log('Error!');
                });
            ) // end of .push() arg
        });

然后在调用systemLog.log之前使用Promise.all()等待所有promise都得到解决,有点像(伪伪代码:)

Promise.all(promises).then(
            systemlog.log({
                message: 'Refresh',
                data: {
                    success: true,
                    note: `Added: ${status.added} & updated: ${status.updated}`,
                },
            });
        )

关于javascript - 异步困惑。处理 API 响应并失去对这段代码中发生的情况的理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60519704/

相关文章:

node.js - 如何将 node_modules 文件夹从 docker 容器中复制到构建机器上?

node.js - Express JS/Node JS : Browsers are not setting cookie when secure=true, sameSite: 'none'

node.js - 函数返回值在nodejs中未定义

javascript - 找不到等待 vue.js 异步函数的方法

javascript - 如何在异步函数中调用父类函数

c# - AntiXSS JavaScriptEncode 获取 HTML 编码?

javascript - Angular ng-view 或 ng-include 不起作用

c# - 单元测试和多个异步任务

javascript - 命名函数是 jsx Prop 的好习惯吗?

javascript - 类似 jQuery 库的模式