Javascript Promise().then 以防止在执行第一次调用之前重新调用该函数
Javascript Promise().then to prevent re-calling the function before the first call be executed
在我的 node.js 应用程序中,使用繁琐的方式从 MSSQL 读取数据,我每 1 秒调用一次以下代码:
- 从服务器获取数据(
fetchStock
函数)并将其保存在临时数组中
- 使用服务器发送事件(SSE)将保存在临时数组中的数据发送到客户端API。
看来在上一个调用完全执行之前的1秒还不够调用fetchStock
函数,所以时不时会出现执行错误。
我把它增加到 5 秒,但仍然每隔一段时间就会遇到同样的问题。
如何使用 Promise().then
来确保 fetchStock
函数在之前的调用完全执行之前不会被重新调用?
var Request = require('tedious').Request;
var Connection = require('tedious').Connection;
var config = {
userName: 'sa',
password: 'pswd',
server: 'xx.xxx.xx.xxx',
options: {
database: 'DB',
rowCollectionOnRequestCompletion: 'true',
rowCollectionOnDone: 'true'
},
};
var sql = new Connection(config);
var addElem = (obj, elem)=> [].push.call(obj, elem);
var result = {}, tmpCol = {}, tmpRow = {};
module.exports = {
displayStock: function (es) {
var dloop = setInterval(function() {
if(result.error !== null)
if (es) es.send(JSON.stringify(result), {event: 'rmSoH', id: (new Date()).toLocaleTimeString()});
if(result.error === null)
if (es) es.send('connection is closed');
}, 1000);
},
fetchStock: function () {
request = new Request("SELECT ItemCode, WhsCode, OnHand FROM OITW where OnHand > 0 and (WhsCode ='RM' or WhsCode ='FG');", function(err, rowCount, rows) {
if (err) {
result = {'error': err};
console.log((new Date()).toLocaleTimeString()+' err : '+err);
}
if(rows)
rows.forEach(function(row){
row.forEach(function(column){
var colName = column.metadata.colName;
var value = column.value;
addElem(tmpCol, {colName: value})
});
addElem(tmpRow,{'item': tmpCol[0].colName, 'Whs': tmpCol[1].colName, 'Qty': tmpCol[2].colName});
tmpCol = {};
});
result = tmpRow;
tmpRow={}
});
sql.execSql(request);
}
}
因为 javascript 是单线程的,像这样的简单代码在客户端就足够了
function () {
if(currentPromise != null){ // define in a closure outside
currentPromise = [..] // call to server which return a promise
currentPromise.then(function(){
currentPromise = null;
});
}
}
我认为您需要的是一个简单的变量来检查是否已经有 运行 请求而不是 Promise
。
var latch = false;
// It will be called only if the previous call is completed
var doFetchStock = () => sql.execSql(new Request("SQL", (err, rowCount, rows) => {
// Your logic dealing with result
// Initializes the latch
latch = false;
});
module.exports = {
fetchStock: function () {
// Check if the previous request is completed or not
if (!latch) {
// Sets the latch
latch = true;
// Fetches stock
doFetchStock();
}
}
};
实际上我经常使用这种模式来允许某些行为只发生一次。
在我的 node.js 应用程序中,使用繁琐的方式从 MSSQL 读取数据,我每 1 秒调用一次以下代码:
- 从服务器获取数据(
fetchStock
函数)并将其保存在临时数组中 - 使用服务器发送事件(SSE)将保存在临时数组中的数据发送到客户端API。
看来在上一个调用完全执行之前的1秒还不够调用fetchStock
函数,所以时不时会出现执行错误。
我把它增加到 5 秒,但仍然每隔一段时间就会遇到同样的问题。
如何使用 Promise().then
来确保 fetchStock
函数在之前的调用完全执行之前不会被重新调用?
var Request = require('tedious').Request;
var Connection = require('tedious').Connection;
var config = {
userName: 'sa',
password: 'pswd',
server: 'xx.xxx.xx.xxx',
options: {
database: 'DB',
rowCollectionOnRequestCompletion: 'true',
rowCollectionOnDone: 'true'
},
};
var sql = new Connection(config);
var addElem = (obj, elem)=> [].push.call(obj, elem);
var result = {}, tmpCol = {}, tmpRow = {};
module.exports = {
displayStock: function (es) {
var dloop = setInterval(function() {
if(result.error !== null)
if (es) es.send(JSON.stringify(result), {event: 'rmSoH', id: (new Date()).toLocaleTimeString()});
if(result.error === null)
if (es) es.send('connection is closed');
}, 1000);
},
fetchStock: function () {
request = new Request("SELECT ItemCode, WhsCode, OnHand FROM OITW where OnHand > 0 and (WhsCode ='RM' or WhsCode ='FG');", function(err, rowCount, rows) {
if (err) {
result = {'error': err};
console.log((new Date()).toLocaleTimeString()+' err : '+err);
}
if(rows)
rows.forEach(function(row){
row.forEach(function(column){
var colName = column.metadata.colName;
var value = column.value;
addElem(tmpCol, {colName: value})
});
addElem(tmpRow,{'item': tmpCol[0].colName, 'Whs': tmpCol[1].colName, 'Qty': tmpCol[2].colName});
tmpCol = {};
});
result = tmpRow;
tmpRow={}
});
sql.execSql(request);
}
}
因为 javascript 是单线程的,像这样的简单代码在客户端就足够了
function () {
if(currentPromise != null){ // define in a closure outside
currentPromise = [..] // call to server which return a promise
currentPromise.then(function(){
currentPromise = null;
});
}
}
我认为您需要的是一个简单的变量来检查是否已经有 运行 请求而不是 Promise
。
var latch = false;
// It will be called only if the previous call is completed
var doFetchStock = () => sql.execSql(new Request("SQL", (err, rowCount, rows) => {
// Your logic dealing with result
// Initializes the latch
latch = false;
});
module.exports = {
fetchStock: function () {
// Check if the previous request is completed or not
if (!latch) {
// Sets the latch
latch = true;
// Fetches stock
doFetchStock();
}
}
};
实际上我经常使用这种模式来允许某些行为只发生一次。