gpt4 book ai didi

javascript - Node JS : How to Promise For Loop

转载 作者:行者123 更新时间:2023-12-03 02:27:40 25 4
gpt4 key购买 nike

我正在尝试创建一个 NodeJS 应用程序。下面是管理员创建新产品时应该调用的代码。大多数代码都可以工作,但是只有在执行其余代码之后(数据库函数是异步的),我才无法渲染 View 。我将大部分代码包装在 Promise(以使某些 block 以正确的顺序执行)和控制台日志(以查明问题)中。

我想指出 console.dir(rejProducts) 位于 console.log(111) 日志和空数组下方。另外,在 for 循环的结束括号之前添加 console.dir(rejProducts) 会记录一个空数组。谢谢!如果您需要更多信息,请告诉我。

app.post('/products/new', function (req, res, next) {
// Async function: find all categories
Category.find(function(err, categories) {
// Hidden count that tells num products to be created by form
var numProducts = req.body[`form-item-count`];
// Array of all rejected products adds
var rejProducts = [];

var promiseLoopProducts = new Promise(function(resolve, reject) {
var promiseProducts = [];
// Loop through all addded products
for (let i = 0; i < numProducts; i++) {
var promiseProductCheck = new Promise(function(resolve, reject) {
var name = validate.sanitize(req.body[`name_${i}`]);
var category = validate.sanitize(req.body[`category_${i}`]);
var price = validate.sanitize(req.body[`price_${i}`].replace(/\$/g, ""));
var stock = validate.sanitize(req.body[`stock_${i}`]);
var image = validate.sanitize(req.body[`image_${i}`]);
var description = validate.sanitize(req.body[`description_${i}`]);

var rejProduct;
var rejFields = { 'name': name, 'category': category, 'price': price,
'stock': stock, 'image': image,
'description': description };
var rejErrors = {};

var productData = {
name: name,
category: category,
price: price,
stock: stock,
image: image,
description: description
};
var promiseCategoryCheck = new Promise(function(resolve, reject) {
if (ObjectId.isValid(category)) {
var promiseCategoryCount = new Promise(function(resolve, reject) {
Category.count({'_id': category}, function(error, count) {
rejErrors['name'] = validate.isEmpty(name);
if (count == 0) rejErrors['category'] = true;
rejErrors['price'] = !validate.isPrice(price);
rejErrors['stock'] = !validate.isInt(stock);

if( validate.isEmpty(name) || !validate.isPrice(price) ||
count == 0 || !validate.isInt(stock) ) {
rejProduct = { 'fields': rejFields, 'errors': rejErrors };
rejProducts.push(rejProduct);
console.dir(rejProducts);
console.log(count);
return resolve();
}
else {
Product.create(productData, function (error, product) {
if (error) return next(error);
console.log(77);
console.dir(rejProducts);
return resolve();
});
}
if (error) return next(error);
});
});
promiseCategoryCount.then(function() {
console.dir(rejProducts);
return resolve();
});
} else {
rejErrors['category'] = true;
rejProduct = { 'fields': rejFields, 'errors': rejErrors };
rejProducts.push(rejProduct);
console.dir(rejProducts);
}
});
promiseCategoryCheck.then(function() {
console.dir(rejProducts);
promiseProducts.push(promiseProductCheck);
console.log(promiseProductCheck);
console.log(promiseProducts);
return resolve();
});
});
promiseProductCheck.then(function() {
console.log(106);
console.dir(rejProducts);
});
}
Promise.all(promiseProducts).then(function() {
console.log(111);
console.dir(rejProducts); // Empty array!
return resolve();
});
});

promiseLoopProducts.then(function() {
console.log(118);
console.dir(rejProducts); // Empty array!
res.render('products/new', { categories: categories, rejProducts: rejProducts });
});

});

});

编辑:我对代码做了一些更改。似乎 util.promisify 没有被识别为函数。我使用的是 Node 9.4。

module.exports = function(app){

const util = require('util');
require('util.promisify').shim();
const validate = require('../functions/validate');

const Category = require('../db/categories');
const Product = require('../db/products');

var ObjectId = require('mongoose').Types.ObjectId;
//Category.find as function that returns a promise
const findCategories = util.promisify(Category.find);

const countCategories = (categoryId) => {
util.promisify(Category.count({'_id': categoryId}));
};

const bodyToProduct = (body, i) => {
var name = validate.sanitize(body[`name_${i}`]);
var category = validate.sanitize(body[`category_${i}`]);
var price = validate.sanitize(body[`price_${i}`].replace(/\$/g, ""));
var stock = validate.sanitize(body[`stock_${i}`]);
var image = validate.sanitize(body[`image_${i}`]);
var description = validate.sanitize(body[`description_${i}`]);
return {
name: name,
category: category,
price: price,
stock: stock,
image: image,
description: description
};
};

app.post('/products/new', function (req, res, next) {
// Async function: find all categories
return findCategories()
.then(
categories=>{
// Hidden count that tells num products to be created by form
var numProducts = req.body[`form-item-count`];
// Array of all rejected products adds
var rejProducts = [];
return Promise.all(
Array.from(new Array(numProducts),(v,i)=>i)
.map(//map [0...numProducts] to product object
i=>bodyToProduct(req.body,i)
)
.map(
product => {
var rejErrors;
var rejName = validate.isEmpty(name);
var rejCategory;
var rejPrice = !validate.isPrice(price);
var rejStock = !validate.isInt(stock);
if (ObjectId.isValid(product.category)) {
return countCategories()
.then(
count=> {
if (count == 0) rejCategory = true;

if(rejName || rejCategory || rejPrice || rejStock ) {
rejErrors = {
name: rejName,
category: rejCategory,
price: rejPrice,
stock: rejStock
}
rejProduct = { 'fields': product, 'errors': rejErrors };
rejProducts.push(rejProduct);
console.dir(rejProducts);
console.log(count);
} else {
Product.create(productData, function (error, product) {
if (error) return next(error);
console.log(77);
console.dir(rejProducts);
});
}
}
).catch(function() {
console.log("Count function failed.");
});
} else {
rejCategory = true;
rejErrors = {
name: rejName,
category: rejCategory,
price: rejPrice,
stock: rejStock
}
rejProduct = { 'fields': product, 'errors': rejErrors };
rejProducts.push(rejProduct);
console.dir(rejProducts);
}
}
)
).then(function() {
res.render('products/new', { categories: categories, rejProducts: rejProducts });
}).catch(function() {
console.log("Promise all products failed.");
});
}
).catch(function() {
console.log("Find categories failed.");
})
});

}

最佳答案

一些提示:如果您的函数超过 100 行,您可能在函数中做了太多事情。

如果您必须以获取产品的方式从请求中获取数据,那么请编写更好的客户端代码(产品应该是不需要清理的产品对象数组)。服务器上需要验证,因为您永远不会相信客户端发送给您的内容。但看看清理后,您甚至不相信客户端脚本发送给您的内容。

尝试编写做小事情的小函数并尝试使用它们。

使用 .map 将类型 a 映射到类型 b(例如,将 req.body 映射到示例代码中的产品数组)。

使用.map的结果作为Promise.all的参数

使用util.promisify将回调函数更改为返回promise的函数,因为您使用的是旧版本的 Node ,所以我添加了promisify的实现:

var promisify = function(fn) {
return function(){
var args = [].slice.apply(arguments);
return new Promise(
function(resolve,reject){
fn.apply(
null,
args.concat([
function(){
var results = [].slice.apply(arguments);
(results[0])//first argument of callback is error
? reject(results[0])//reject with error
: resolve(results.slice(1,results.length)[0])//resolve with single result
}
])
)
}
);
}
};

module.exports = function(app){
const validate = require('../functions/validate');
const Category = require('../db/categories');
const Product = require('../db/products');
var ObjectId = require('mongoose').Types.ObjectId;
//Category.find as function that returns a promise
const findCategories = promisify(Category.find.bind(Category));
const countCategories = (categoryId) => {
promisify(Category.count.bind(Category))({'_id': categoryId});
};
const createProduct = promisify(Product.create.bind(Product));
const REJECTED = {};
const bodyToProduct = (body, i) => {
var name = validate.sanitize(body[`name_${i}`]);
var category = validate.sanitize(body[`category_${i}`]);
var price = validate.sanitize(body[`price_${i}`].replace(/\$/g, ""));
var stock = validate.sanitize(body[`stock_${i}`]);
var image = validate.sanitize(body[`image_${i}`]);
var description = validate.sanitize(body[`description_${i}`]);
return {
name: name,
category: category,
price: price,
stock: stock,
image: image,
description: description
};
};

const setReject = product => {
var rejErrors;
var rejName = validate.isEmpty(product.name);
var rejCategory;
var rejPrice = !validate.isPrice(product.price);
var rejStock = !validate.isInt(product.stock);
const countPromise = (ObjectId.isValid(product.category))
? countCategories()
: Promise.resolve(0);
return countPromise
.then(
count => {
if (count == 0) rejCategory = true;

if (rejName || rejCategory || rejPrice || rejStock) {
rejErrors = {
type:REJECTED,
name: rejName,
category: rejCategory,
price: rejPrice,
stock: rejStock
}
return rejErrors;
}
return false;
}
);
};

const productWithReject = product =>
Promise.all([
product,
setReject(product)
]);

const saveProductIfNoRejected = ([product,reject]) =>
(reject===false)
? Product.create(product)
.catch(
err=>({
type:REJECTED,
error:err
})
)
: reject;

app.post('/products/new', function (req, res, next) {
// Async function: find all categories
return findCategories()
.then(
categories => {
// Hidden count that tells num products to be created by form
var numProducts = req.body[`form-item-count`];
// Array of all rejected products adds
var rejProducts = [];
return Promise.all(
Array.from(new Array(numProducts), (v, i) => i)
.map(//map [0...numProducts] to product object
i => bodyToProduct(req.body, i)
)
.map(
product=>
productWithReject(product)
.then(saveProductIfNoRejected)
)
).then(
results =>
res.render(
'products/new',
{
categories: categories,
rejProducts: results.filter(x=>(x&&x.type)===REJECTED)
}
)
).catch(
error=>
console.log("Promise all products failed.",error)
);
}
).catch(
error=>
console.log("Find categories failed.",error)
)
});
}

关于javascript - Node JS : How to Promise For Loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48877519/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com