NodeJS My SQL 查询与 Chain Promise

2024-03-13

我有3个函数,我想逐步调用这个函数,例如当我调用第一个函数并获取结果时,我必须调用第二个函数并传递从第一次调用返回的参数。在完成第二个调用后,我必须调用第三个函数并传递从第二个函数返回的参数。

#1:

getCategory = function (branch_id) {
    var deferred = q.defer();
    var categoryData;
    var query = 'SELECT id,name,price,currency FROM category  where branch_id=?';
    pool.getConnection(function (err, connection) {
        connection.query(query, [branch_id], function (error, row, fields) {
            if (error) {
                deferred.reject(error);
            } else {
                connection.release();
                deferred.resolve(row);
            }
        });
    });
    return deferred.promise; }

#2:

getRoom = function (branch_id, categoryID) {
    var deferred = q.defer();
    var roomData;
    var roomSql = 'SELECT id,room_no,name,price,currency FROM room  where branch_id=? and category_id=?';
    pool.getConnection(function (err, connection) {
        connection.query(roomSql, [branch_id, categoryID], function (error, row, fields) {
            if (err) {
                deferred.reject(err);
            } else {
                connection.release();
                deferred.resolve(row);
            }
        });
    });
    return deferred.promise;
}

#3:

getReservationL = function (room_id, start_date, end_date) {
    var deferred = q.defer();
    var reservationData;
    var reservationSql = 'SELECT d.id,d.create_date,d.update_date,d.room_id,d.status_id,d.start_date,d.end_date, ' +
        ' s.name as status_name,a.id as reservation_id,a.person_no as person_no, p.first_name,p.last_name,p.email ' +
        ' FROM reservation_detail d ' +
        ' inner join reservation_status s on d.status_id=s.id ' +
        ' inner join reservation a on d.reservation_id=a.id ' +
        ' inner join person p on a.person_no=p.personal_no ' +
        ' where d.room_id=? and d.start_date >? and d.start_date<?';
    pool.getConnection(function (err, connection) {
        connection.query(reservationSql, [room_id, start_date, end_date], function (error, row, fields) {
            if (err) {
                deferred.reject(err);
            } else {
                connection.release();
                deferred.resolve(row);
            }
        });
    });
    return deferred.promise;
}

我需要这样的东西:

data = getCategory()
for(i=0;i<data.length;i++){
   data[i].room = getRoom(data[i].id);
   for(j=0;j<data[i].room[j].length;j++){
      data[i].room[j].reservation = getReservationL(data[i].room[j].id);
   }
}

如何在 NodeJS 中使用 Promise 或 Callback 来实现这个伪代码。我更喜欢使用承诺。

UPDATE#1第二次迭代后我有这样的数据

[
  {
    "id": 64,
    "name": "VIP",
    "price": 116.5,
    "currency": "USD",
    "room": [
      {
        "id": 44,
        "room_no": "101",
        "name": "A",
        "price": 100,
        "currency": "EUR"
      },
      {
        "id": 274,
        "room_no": "505",
        "name": "a",
        "price": 1,
        "c\r\nurrency": "GEL"
      }
    ]
  },
  {
    "id": 74,
    "name": "SUPER VIP",
    "price": 110,
    "currency": "EUR",
    "room": [
      {
        "id": 54,
        "room_no": "102",
        "name": "A",
        "price": 100,
        "currency": "GEL"
      },
      {
        "id": 284,
        "room_no": "606",
        "name": "a",
        "price": 1,
        "currency": "GEL"
      }
    ]
  },
  {
    "id": 84,
    "name": "DOUBLE",
    "price": 110,
    "currency": "GEL",
    "room": [
      {
        "id": 204,
        "room_no": "103",
        "name": "b",
        "price": 120,
        "currency": "GEL"
      }
    ]
  }
]

我想迭代每个房间的每个类别。

     getCategory(branch_id).then(firstRecords => {
        let promises = firstRecords.map(function (record) {
            return getRoom(branch_id, record.id)
                .then(roomData => {
                    var res = Object.assign({}, record, { room: roomData });
                    return res;
                })
        });
        return Promise.all(promises);
//HERE i have data that is placed above.
    }).then(secondRecords => {
        let promises = secondRecords.map(function (category) {
            return category.room;
        }).map(function (rooms) {
            console.log('SECOND', rooms);
            return rooms;
        }).map(function (reservation) {
            console.log('THERD', reservation);
            return reservation;
        })
        return Promise.all(promises);
    }).then(reservation => {
        console.log("Reservation", reservation);
    })

UPDATE#2最终解决方案在这里

getCategory(branch_id) .then( categories => {

  let roomPromises = categories.map( category => {
    return getRoom(branch_id, category.id)
    .then( rooms => Object.assign({}, category, { rooms }) )   });

  return Promise.all(roomPromises) }) .then( category_rooms => {

  let finalPromise = category_rooms.map( category => {

    let reservationPromises = category.rooms.map( room => {
      return getReservationL(room.id, start_date, end_date)
      .then( reservations => Object.assign({}, room, { reservations }) )
    })

    return Promise.all(reservationPromises)
    .then( room_reservations => {
      return Object.assign({}, category, { rooms: room_reservations })
    });   })

  // const flattenPromise = finalPromise.reduce( (a, b) => a.concat(b), []);   // return Promise.all(flattenPromise);
     return Promise.all(finalPromise) }) .then( data => console.log('final: ', data) )

您可以使用以下方式解决承诺.then并且可以链then以同步方式解决多个承诺。

也许这会解决您的用例。

getCategory()
.then( firstRecords => {

  console.log('firstRecords: ', firstRecords);

  let promises = firstRecords.map( record => getRoom(record) );
  return Promise.all(promises);
})
.then( secondRecords => {

  console.log('secondRecords: ', secondRecords);

  let promises = secondRecords.map( record => getReservationL(record) );
  return Promise.all(promises);
})
.then( thirdRecords => {

  console.log('thirdRecords: ', thirdRecords);
})

参考: 先承诺后链接 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining

then 方法返回一个允许方法链接的 Promise。

如果作为处理程序传递给 then 的函数返回一个 Promise,则等效的 Promise 将暴露给方法链中后续的 then

参考: 答应一切 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Promise.all() 方法返回一个 Promise,当可迭代参数中的所有 Promise 都已解析或可迭代参数不包含 Promise 时,该 Promise 就会解析。它以第一个拒绝的承诺为理由拒绝。

Promise.all([ { key: 1 }, Promise.resolve(3), 1, true ])
.then( results => {
    results[0]; // { key: 1 }
    results[1]; // 3
    results[2]; // 1
    results[3]; // true
})

更新#1

Promise.all只接受 Promise 数组,而不接受键上带有 Promise 的对象。

# wrong
Promise.all([
    { key: Promise.resolve(1) },
    { key: Promise.resolve(2) },
    { key: Promise.resolve(3) },
])

# right
Promise.all([ 
    Promise.resolve(1), 
    Promise.resolve(2), 
    Promise.resolve(3) 
])

你可以做这样的事情来实现你在评论中提到的。

getCategory(branch_id)
.then( firstRecords => {

  console.log('firstRecords: ', firstRecords);

  let promises = firstRecords.map( record => {
    return getRoom(branch_id, record.id)
    .then( roomData => Object.assign({}, record, { room : roomData }) )
  });
  
  return Promise.all(promises)
  
})

如果您想附加第一个和第二个 Promise 的数据,那么只需解析那里的 Promise 即可在一个位置访问这两个 Promise 的数据。

更新#2

正如您在评论中提到的,这段代码可能会对您有所帮助。

getCategory(branch_id)
.then( categories => {

  let roomPromises = categories.map( category => {
    return getRoom(branch_id, category.id)
    .then( rooms => Object.assign({}, category, { rooms }) )
  });

  return Promise.all(roomPromises)

})
.then( category_rooms => {

  let finalPromise = category_rooms.map( category => {
    
    let reservationPromises = category.rooms.map( room => {
      return getReservationL(room.id, start_date, end_date)
      .then( reservations => Object.assign({}, room, { reservations }) )
    })

    return Promise.all(reservationPromises)
    .then( room_reservations => {
      return Object.assign({}, category, { rooms: room_reservations })
    });
  })
  
  return Promise.all(finalPromise)
})
.then( data => console.log(data) )
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NodeJS My SQL 查询与 Chain Promise 的相关文章

随机推荐

  • Web 应用程序作为服务自动更新,无需启动器

    如果应用程序是没有启动器的 Web 应用程序即服务 install4j 中的自动更新功能是否有效 我尝试了网络资源中提到的许多方法 但没有成功 请帮忙 我正在使用 install4j Windows 版本 6 1 6 编辑1 英戈 凯格尔
  • Bootstrap 4 - Scrollspy 不起作用

    我已经按照BS4中如何使用Scrollspy的文档进行操作 但它不起作用 那么我该如何解决它 我的身体有posistion relative 这是我的身体标签 这是导航栏的 HTML
  • 对 data.frame 或矩阵中的行求和

    我有一个非常大的数据框 其中行作为观察值 列作为遗传标记 我想创建一个新列 其中包含使用 R 的每个观察的选定列数的总和 如果我有 200 列和 100 行 那么我希望创建一个有 100 行的新列 其中包含第 43 至 167 列的总和 这
  • 异步套接字 - 处理错误的 socket.AcceptAsync 值

    Socket 类有一个方法 AcceptAsync 它返回 true 或 false 我原以为 false 返回值是一个错误条件 但在 Microsoft 为异步套接字提供的示例中 它们在检查失败后同步调用回调函数 如下所示 public
  • 如何制作一个钝角的按钮?

    如何制作一个钝角的按钮 我希望发生这样的事 我就这样来到这里 我的代码 Fiddle https jsfiddle net soledar10 nLt9qd5s box sizing border box btn display inlin
  • Android mkdirs() 不工作

    我正在开发我的第一个 Android 应用程序 在尝试创建目录来保存录制的视频文件时遇到了问题 我的主要活动有一个方法buttonOnClickRecord调用使用 android 相机的意图 我还在这个方法调用期间创建了一个文件 并且我正
  • 如何找出方法或函数的调用者是谁? [复制]

    这个问题在这里已经有答案了 我想编写一个调试函数或方法来帮助打印有用的信息 当它被调用时 我需要 调用对象的内存地址 如果由对象调用 调用者的方法签名 或方法的名称 或函数的名称 拥有该方法或函数的类名 是否可以在不传递一大堆参数的情况下获
  • 为什么我无法使用 Puppeteer 访问 hideFunction() 函数中的“窗口”?

    我有一个非常简单的傀儡师 https github com GoogleChrome puppeteer使用的脚本exposeFunction https github com GoogleChrome puppeteer blob mas
  • Swift 中数组的 endIndex 的正确行为是什么?

    endIndex 返回与 count 相同的值 这是正确的行为还是错误 var ar 1 2 3 4 ar count 4 ar endIndex 4 count是集合中的项目数 而endIndex is the Index 来自Colle
  • Android - 移动网络设置菜单(Jelly Bean)

    以下代码不适用于 Jelly Bean Android 4 1 final ComponentName cn new ComponentName com android phone com android phone Settings fi
  • ios 中纹理的多重采样渲染

    我正在尝试在启用多重采样的 ios 中渲染到纹理 然后在最终输出中使用该纹理 这可能吗 到目前为止 我只得到了黑色纹理或锯齿图像 我正在使用的代码是 glGenTextures 1 texture glBindTexture GL TEXT
  • C# 没有边界检查的 byte[] 比较

    我正在寻找性能高效的方法来比较两个 byte 是否相等 大小超过 1 MB 因此每个数组元素的开销应最小化 我的目标是超越SequenceEqual http msdn microsoft com en us library bb34856
  • python tkinter 列表框事件绑定

    我无法让事件绑定与 python tkinter 一起使用 我只是尝试单击并打印位置 但每次执行此操作时 结果都是 1 这是我的代码 from Tkinter import import Tkinter class make list Tk
  • spring junit 加载应用程序上下文进行测试

    我的 WEB INF 目录下有一些 XML 文件 歌词BaseApp servlet xml 休眠文件 数据源 xml beans xml servlet xml 导入其他 xml 文件
  • 如何旋转图像pygame的蒙版

    您好 我在旋转对象的蒙版时遇到问题 旋转蒙版仍处于与原始图像相同的位置 重点是在赛道上移动掩模以形成碰撞 def init self x y height width self x x width 2 self y y height 2 s
  • Angular - 使用 Restangular 时中止 ajax 请求

    我有一个方法调用角度服务 从而通过该服务发出 ajax 请求 我需要确保如果多次调用此方法 则先前的请求将被中止 如果尚未解决 该方法可以被多次调用 这个方法其实是来自ngTable上的ngTableParams getData funct
  • 如何监听 MongoDB 集合的更改?

    我正在创建一种后台作业队列系统 使用 MongoDB 作为数据存储 在派生工作人员来处理作业之前 如何 侦听 对 MongoDB 集合的插入 我是否需要每隔几秒轮询一次以查看与上次相比是否有任何更改 或者我的脚本是否可以等待插入发生 这是我
  • Web应用程序不会加入Infinispan集群

    我最近一直在玩 Infinispan 之前没有使用 Infinispan 的经验 我遇到了一个有趣的问题 我想知道是否有人能够阐明它 我有一个独立的 Java 应用程序 GridGrabber jar 它捆绑了 Infinispan jar
  • 使用后台附件:在 ipad 上的 safari 中修复

    我希望重新创建类似于科普应用程序的效果 基本上有一个大的背景图像 然后在其上有 HTML CSS 层 当用户滚动内容时 图像的背景位置应保持在原位 而不是滚动 显然 在 常规 浏览器中我会使用background attachment fi
  • NodeJS My SQL 查询与 Chain Promise

    我有3个函数 我想逐步调用这个函数 例如当我调用第一个函数并获取结果时 我必须调用第二个函数并传递从第一次调用返回的参数 在完成第二个调用后 我必须调用第三个函数并传递从第二个函数返回的参数 1 getCategory function b