循环内的异步承诺
Async promises inside loop
我知道这是一个有很多信息的话题,但我仍然无法解决这个问题。
我正在使用连接到 mysql 服务器的 NodeJs,我有一个数组,我需要迭代数组并对数据做一些事情,问题是我需要查询mysql 服务器,但我需要 for 循环等到我得到查询结果,我已经尝试了很多东西,现在我正在尝试使用 .each 蓝鸟方法,但仍然无法正常工作,这是我的代码。
初始函数为Notification.getByUser
提前致谢
'use strict';
var Promise = require("bluebird");
module.exports = function(Notifications) {
Notifications.execute = function(sql, itemId) {
return new Promise((resolve, reject) => {
this.dataSource.connector.execute(sql, (e, result) => {
console.log('-----RESULT----', itemId);
console.log(result);
console.log('-----ERROR-----', itemId);
console.log(e);
if (result.length === 0) {
resolve(false);
} else {
resolve(true);
}
});
});
};
Notifications.isMatching = function(item, user, type) {
return new Promise((resolve, reject) => {
console.log(type, item, user);
if (item !== null) {
if (item !== user) {
resolve(false);
}
}
resolve(true);
});
};
Notifications.getByUser = function(userId, isZolver, countryId, cityId, userState, cb) {
var where = { status: 1 };
var plainText = '';
var items = Notifications.find({ where });
Promise.each(items, item => {
return Notifications.isMatching(item.isZolver, isZolver, 'isZolver')
.then(() => {
Notifications.isMatching(item.cityId, cityId, 'cityId');
})
.then(() => {
if(item.extraCondition !== null && item.extraCondition !== '') {
var sql = item.extraCondition.replace(/:user_id/g, userId);
// console.log(sql);
Notifications.execute(sql, item.id)
.then(render => console.log('extraCondition', render));
} else {
console.log('extraCondition', true);
}
});
}).then(res => {
// console.log('res del loop', res);
});
cb(null, 'ok');
};
};
您的代码存在几个问题:
为了链接承诺,您必须确保 return 您在 then
回调中创建的承诺
您不需要为立即可用的结果创建承诺 (isMatching
)
then
回调总是在承诺实现时执行。你是否做 resolve(false)
并不重要:即使承诺的值为 false
这仍然会使承诺实现并触发 then
回调。
您的代码中有一些未知数,例如 Notifications.find
,以及您正在执行哪种 SQL:是否 return 结果集,如果是,您是否会有兴趣获得该结果而不是仅仅解析为布尔值吗?
无论如何,这里有一些应用更正:
'use strict';
var Promise = require("bluebird");
module.exports = function(Notifications) {
Notifications.execute = function(sql, itemId) {
return new Promise((resolve, reject) => {
this.dataSource.connector.execute(sql, (e, result) => {
console.log('-----RESULT----', itemId);
console.log(result);
console.log('-----ERROR-----', itemId);
console.log(e);
resolve (result.length !== 0); // The `if ... else` is overkill
});
});
};
//You don't need isMatching to return a promise
Notifications.isMatching = function(a, b) {
return a === null || a === b;
};
Notifications.getByUser = function(userId, isZolver, countryId, cityId, userState) {
var where = { status: 1 };
var items = Notifications.find({ where })
// use filter() to limit the items to those you want to execute the SQL for
.filter(item => {
return Notifications.isMatching(item.isZolver, isZolver)
&& Notifications.isMatching(item.cityId, cityId)
&& item.extraCondition !== ''
});
// Return the promise! (don't go back to the old callback system!)
return Promise.each(items, item => {
var sql = item.extraCondition.replace(/:user_id/g, userId);
// Return the promise!
return Notifications.execute(sql, item.id);
}).then(res => {
console.log('res del loop', res);
});
};
};
注意Notifications.getByUser
的签名没有最后的回调参数:一旦你开始使用promise,你应该继续使用它们,所以当你调用这个函数时,调用结果的then
方法就像你会为任何承诺做的那样:
Notifications.getByUser( .......arguments....).then( function () {
// do something...
});
我知道这是一个有很多信息的话题,但我仍然无法解决这个问题。
我正在使用连接到 mysql 服务器的 NodeJs,我有一个数组,我需要迭代数组并对数据做一些事情,问题是我需要查询mysql 服务器,但我需要 for 循环等到我得到查询结果,我已经尝试了很多东西,现在我正在尝试使用 .each 蓝鸟方法,但仍然无法正常工作,这是我的代码。
初始函数为Notification.getByUser
提前致谢
'use strict';
var Promise = require("bluebird");
module.exports = function(Notifications) {
Notifications.execute = function(sql, itemId) {
return new Promise((resolve, reject) => {
this.dataSource.connector.execute(sql, (e, result) => {
console.log('-----RESULT----', itemId);
console.log(result);
console.log('-----ERROR-----', itemId);
console.log(e);
if (result.length === 0) {
resolve(false);
} else {
resolve(true);
}
});
});
};
Notifications.isMatching = function(item, user, type) {
return new Promise((resolve, reject) => {
console.log(type, item, user);
if (item !== null) {
if (item !== user) {
resolve(false);
}
}
resolve(true);
});
};
Notifications.getByUser = function(userId, isZolver, countryId, cityId, userState, cb) {
var where = { status: 1 };
var plainText = '';
var items = Notifications.find({ where });
Promise.each(items, item => {
return Notifications.isMatching(item.isZolver, isZolver, 'isZolver')
.then(() => {
Notifications.isMatching(item.cityId, cityId, 'cityId');
})
.then(() => {
if(item.extraCondition !== null && item.extraCondition !== '') {
var sql = item.extraCondition.replace(/:user_id/g, userId);
// console.log(sql);
Notifications.execute(sql, item.id)
.then(render => console.log('extraCondition', render));
} else {
console.log('extraCondition', true);
}
});
}).then(res => {
// console.log('res del loop', res);
});
cb(null, 'ok');
};
};
您的代码存在几个问题:
为了链接承诺,您必须确保 return 您在
then
回调中创建的承诺您不需要为立即可用的结果创建承诺 (
isMatching
)then
回调总是在承诺实现时执行。你是否做resolve(false)
并不重要:即使承诺的值为false
这仍然会使承诺实现并触发then
回调。
您的代码中有一些未知数,例如 Notifications.find
,以及您正在执行哪种 SQL:是否 return 结果集,如果是,您是否会有兴趣获得该结果而不是仅仅解析为布尔值吗?
无论如何,这里有一些应用更正:
'use strict';
var Promise = require("bluebird");
module.exports = function(Notifications) {
Notifications.execute = function(sql, itemId) {
return new Promise((resolve, reject) => {
this.dataSource.connector.execute(sql, (e, result) => {
console.log('-----RESULT----', itemId);
console.log(result);
console.log('-----ERROR-----', itemId);
console.log(e);
resolve (result.length !== 0); // The `if ... else` is overkill
});
});
};
//You don't need isMatching to return a promise
Notifications.isMatching = function(a, b) {
return a === null || a === b;
};
Notifications.getByUser = function(userId, isZolver, countryId, cityId, userState) {
var where = { status: 1 };
var items = Notifications.find({ where })
// use filter() to limit the items to those you want to execute the SQL for
.filter(item => {
return Notifications.isMatching(item.isZolver, isZolver)
&& Notifications.isMatching(item.cityId, cityId)
&& item.extraCondition !== ''
});
// Return the promise! (don't go back to the old callback system!)
return Promise.each(items, item => {
var sql = item.extraCondition.replace(/:user_id/g, userId);
// Return the promise!
return Notifications.execute(sql, item.id);
}).then(res => {
console.log('res del loop', res);
});
};
};
注意Notifications.getByUser
的签名没有最后的回调参数:一旦你开始使用promise,你应该继续使用它们,所以当你调用这个函数时,调用结果的then
方法就像你会为任何承诺做的那样:
Notifications.getByUser( .......arguments....).then( function () {
// do something...
});