节点承诺循环

这是我的问题:

我正在向我的数据库中的一个表发出请求,结果那个请求我想向另一个表发出两个请求,这两个请求的结果想要将它们添加到主请求(第一个)。 问题是,这两个请求实际上是做出来的,但是当试图把结果放在主要结果中的时候不会让我。 第二个然后也运行时,第一个没有结束(第一个循环结束应该结束)

也许错误是非常愚蠢的,我是有承诺的新手。

谢谢

提取代码:

var express = require("express"); var app = express(); var Promise = require('bluebird'); var bodyParser = require('body-parser') var mysql = require('promise-mysql'); app.get('/misPartidos', function (req, res) { var query = conexion.query('SELECT partidos.id_partido, partidos.id_torneo, partidos.nlocal, partidos.nvisitante, partidos.idlocal,partidos.idvisitante, partidos.jornada, partidos.glocal, partidos.gvisitante, partidos.fecha, torneos.nombre_torneo, partidos.estado, torneos.version, torneos.modo, torneos.tipo FROM partidos INNER JOIN equipos ON(equipos.id_equipo = partidos.idlocal OR equipos.id_equipo = partidos.idvisitante) INNER JOIN participantes ON(equipos.id_equipo = participantes.id_equipo AND equipos.id_torneo = participantes.idtorneo_part) INNER JOIN torneos ON(participantes.idtorneo_part = torneos.id_torneo) WHERE participantes.username = "'+ req.query.usuario + '" ORDER BY jornada ASC') .then(function(success){ for(var x in success){ conexion.query('SELECT username,nombre_eq FROM equipos WHERE id_equipo = '+success[x].idlocal) .then(function(local){ success[x].local = local[0].username; }); conexion.query('SELECT username, nombre_eq FROM equipos WHERE id_equipo = '+success[x].idvisitante) .then(function(visitante){ success[x].visitante = visitante[0].username; }); return success; } }).then(function(resultado){ console.log(results); }).catch(function(error){ console.log(error); }); }); 

假设你的success参数是一个查询结果数组,你可以这样做:

 var express = require("express"); var app = express(); var Promise = require('bluebird'); var bodyParser = require('body-parser') var mysql = require('promise-mysql'); app.get('/misPartidos', function (req, res) { var queryString = 'SELECT partidos.id_partido, partidos.id_torneo, partidos.nlocal, partidos.nvisitante, partidos.idlocal,partidos.idvisitante, partidos.jornada, partidos.glocal, partidos.gvisitante, partidos.fecha, torneos.nombre_torneo, partidos.estado, torneos.version, torneos.modo, torneos.tipo FROM partidos INNER JOIN equipos ON(equipos.id_equipo = partidos.idlocal OR equipos.id_equipo = partidos.idvisitante) INNER JOIN participantes ON(equipos.id_equipo = participantes.id_equipo AND equipos.id_torneo = participantes.idtorneo_part) INNER JOIN torneos ON(participantes.idtorneo_part = torneos.id_torneo) WHERE participantes.username = "'+ req.query.usuario + '" ORDER BY jornada ASC'; Promise.map(conexion.query(queryString), function(item) { return Promise.all([ conexion.query('SELECT username,nombre_eq FROM equipos WHERE id_equipo = '+item.idlocal).then(function(local) { item.local = local[0].username; }), conexion.query('SELECT username, nombre_eq FROM equipos WHERE id_equipo = '+item.idvisitante).then(function(visitante){ item.visitante = visitante[0].username; }) ]).then(function() { // make the return value from `Promise.all()` be the item // we were iterating return item; }); }).then(function(results) { // array of results here console.log(results); }).catch(function(err) { // error here console.log(err); }); }); 

这样做如下:

  1. 使用Bluebird的Promise.map()遍历第一个查询的所有结果
  2. 在每次迭代中使用Promise.all() ,以便每次迭代都返回一个表示您所做的子查询的单个promise。
  3. 作为每次迭代的结果返回单个项目
  4. 当所有的迭代和子查询都完成后,您应该得到一个结果数组。

有承诺的麻烦是可以的。 这是一件棘手的事情。

首先,保存这篇关于承诺和问题的伟大文章 。

关于你的问题。 问题是承诺是asynchronous和for循环不是。 你需要使用map-loop并返回它。 这将保证所有的行动都将完成,只有在第二个承诺将开始。 有两种方法:

  • 使用Promise(ES6): return Promise.all( array_of_your_elements.map( elem => { // some actions // ... return; }))

  • 使用async-await(ES7): async function_name() { await* array_of_your_elements.map( elem => { // some actions // ... return; }) }

我更喜欢第二种方式。

重要提示 :您应该总是在地图上使用返回。 它可以是空的返回(如在示例中)或其他东西。 如果你会返回,例如,string在每一次迭代,它会给你一个string的承诺数组。

享受承诺!