如何将链式 Promise 与数组的 for 循环一起使用?
Posted
技术标签:
【中文标题】如何将链式 Promise 与数组的 for 循环一起使用?【英文标题】:How to use chaining promise together with for loops of arrays? 【发布时间】:2019-07-02 09:55:51 【问题描述】:所以,我有这个代码。我正在尝试永远调试它。我不知道为什么它返回错误。我可能忘记了一些承诺,或者我的 array.push 有问题,因为当我查看日志时,它会在我将一些对象推入数组的地方抛出错误。
到目前为止,这是我的代码:
router.post('/inventory/product/stocks/add/(:id)', authenticationMiddleware(), function(req, res, next)
const db = require('../db.js')
var product_no = req.params.id
var cog = req.body.cog
var size_slug = req.body.size_slug
var size_name = req.body.size_name
var rowinserted = 0
var initial_stock = req.body.initial_stock
var stock_id = new Array
var batch_id = new Array
var stock = new Array
var batch = new Array
new Promise(function(resolve, reject)
console.log('one');
// Getting product product_slug for product_sku
let sql = `SELECT product_slug
FROM inventory_tbl
WHERE product_no = ?`
db.query(sql, [req.params.id], (error, results, fields) =>
if (error)
throw error;
else
var product_slug = results[0].product_slug
resolve(product_slug)
)
)
.then(function(value)
console.log('two');
// Insert product sizes together with its initial stock
for (var x = 0; x < size_slug.length; x++)
var product_sku = value + size_slug[x]
var slug = size_slug[x]
var name = size_name[x]
var initial_stock = initial_stock[x]
console.log(product_sku);
if (size_slug[x] != '')
stock.push(
product_sku: product_sku,
product_no: product_no,
size_slug: slug,
size_name: name,
total_stock: initial_stock,
available_stock: initial_stock
)
console.log(stock);
for (var x = 0; x < size_slug.length; x++)
var product_sku = value + size_slug[x]
var initial_stock = initial_stock[x]
if (size_slug[x] != '')
batch.push(
product_no: product_no,
product_sku: product_sku,
production_date: mysql.raw('CURRENT_TIMESTAMP'),
batch_cog: cog,
initial_stock: initial_stock,
stock_left: initial_stock
)
console.log(batch);
return value
)
.then(function(value)
console.log('three');
// Insert rows to product_tbl and stock_tbl
for (var i = 0; i < stock.length; i++)
let sql = `INSERT INTO product_tbl(product_sku, product_no, size_slug, size_name, total_stock, available_stock) VALUES (?, ?, ?, ?, ?, ?)`
db.query(sql, [stock[i].product_sku, req.params.id, stock[i].size_slug, stock[i].size_name, stock[i].total_stock, stock[i].available_stock], (error, results, fields) =>
if (error) throw error
db.query(`SELECT LAST_INSERT_ID() AS id;`, (error, results, fields) =>
stock_id[i] = results[0].id
)
)
sql = `INSERT INTO stocks_tbl(product_no, product_sku, production_date, batch_cog, initial_stock, stock_left) VALUES (?, ?, CURRENT_DATE, ?, ?, ?)`
db.query(sql, [req.params.id, batch[i].product_sku, batch[i].batch_cog, batch[i].initial_stock, batch[i].stock_left], (error, results, fields) =>
if (error) throw error
db.query(`SELECT LAST_INSERT_ID() AS id;`, (error, results, fields) =>
batch_id[i] = results[0].id
)
)
rowsupdated++
return value
)
.then(function(value)
console.log('four');
// Render the web page
if (rowinserted != sizeslug.length)
req.flash('error', error)
res.redirect('/admin/inventory/product/stock/add/' + req.params.id)
else
req.flash('success', 'Data added successfully!')
res.redirect('/admin/inventory/product/stock/add/' + req.params.id)
)
.catch(function(error)
console.log('error');
// Error handler
for (var i = 0; i < rowinserted; i++)
let sql = `DELETE FROM product_tbl WHERE product_sku = ?`
db.query(sql, [stock_id[i]], (error, results, fields) =>
if (error) throw error
)
sql = `DELETE FROM stocks_tbl WHERE product_sku = ?`
db.query(sql, [batch_id[i]], (error, results, fields) =>
if (error) throw error
)
res.redirect('/admin/inventory/product/stock/add/' + req.params.id)
)
)
我的日志返回:
一个
两个
错误
编辑:进程在 console.log('two') 之后停止(我不确定具体的行,但根据日志输出),因为我尝试在for 循环,但它们不会在那里继续。它只是转到 .catch/error。
【问题讨论】:
您是否考虑过为此使用库?如果是,我建议使用when
。它真的很强大。 github.com/cujojs/when
如果你返回的value
参数不是一个promise,那么你就不能真正用.then
链接函数,因为它没有返回一个promise
@Strawberry JS 有三个不同的引号,单引号、双引号和反引号。 Single 和 double 没有行为差异,但反引号允许您执行多行字符串和模板。
@MichaelWestcott 够公平的!
回调地狱 :) 如果您使用过任何库,例如 Q 或 bluebird 甚至 async/await(if nodejs>6.11),那么您将永远不会遇到这样的错误。
【参考方案1】:
而不是在console.log('error');
中输出字符串,而是转储您在catch
处理程序中收到的实际error
对象。它将提供有关失败原因和位置的更多详细信息。我怀疑console.log('two');
之后的代码会抛出异常,然后你不小心把它吞到下面了。
考虑将您的代码拆分为单独的主题函数。这样您就可以更轻松地维护和发现错误(或拼写错误)。
【讨论】:
【参考方案2】:查看输出,我可以看到 console.log(product_sku);
这没有被打印出来。所以,实际上问题是var initial_stock = initial_stock[x]
。您已经声明了与全局变量(到您的 route.post 回调函数)同名的局部变量(到您的 then 回调函数),现在您的全局 initial_stock
变量被本地变量掩盖,这不是一个数组(实际上是不明确的)。因此,尝试将变量名称更改为 then
块中的其他名称,看看问题是否消失。
希望这会有所帮助。
【讨论】:
没有窗口,代码是node.js。无论如何, intial_stock 不是全局的,它的范围是 router.post 回调函数。除此之外,您可能走在正确的轨道上 啊,我明白了。我想我错过了上述上下文并专注于有问题的代码。我将编辑我的答案。谢谢@MichaelWestcott以上是关于如何将链式 Promise 与数组的 for 循环一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
使用fetch时如何在for循环中动态循环多个promise?