Javascript 闭包, 老生常谈。
近期遇到问题时,在可编辑表格中键盘快速的上下移动,每次移动会触发change事件,而change事件中执行的是异步访问后台后填充行(且会有多次访问的情况发生,使用Promise数组同步执行)。
此时的现象为,表格中行数据不完整,有的有的没有。
原来的代码如下:
const rowChangeTasks = []
// 原来的代码,单行逐行填充
arrayValue.forEach((value, idx) => {
const changeSqls = changesql.split(';')
changeSqls.forEach(cSQL => {
const p = () => {
return new Promise((resolve, reject) => {
const _this = this
this.selectedRow = table.tableFullData[theRowIndex + idx]
this.selectedRow[columnName] = value
const sql = this.replaceAllParams(cSQL)
this.ExecCmd({ sql: sql, callName: '表格单元格change事件,执行存储过程', callMethod: 'tableCellDataChangeHandler' }).then(res => {
return this.getErrorData(res, 'subtable')
}).then(res => {
if (res && res.length) {
const rowData = Object.assign({}, res[0])
if (Object.prototype.hasOwnProperty.call(rowData, _this.keyname)) {
delete rowData[_this.keyname]
}
// rowData[this.keyname] = `-${idx + theRowIndex}`
const currentColumnObject = {}
currentColumnObject[columnName] = value
Object.assign(table.tableFullData[theRowIndex + idx], currentColumnObject, rowData)
return table.cellDefaultValue(table.tableFullData[theRowIndex + idx], theRowIndex + idx)
} else {
return Promise.resolve()
}
}).then(() => {
table.calcFormulasHandler(table.tableFullData[theRowIndex + idx], columnName) // 计算公式
resolve()
}).catch(error => {
reject(error)
})
})
}
rowChangeTasks.push(p)
})
if (idx) {
table.tableFullData[theRowIndex + idx][columnName] = value
}
})
this.common.doPromiseArray(rowChangeTasks).then(() => {
console.log('结束')
})
且后,我想到了用闭包的方式来处理,新的代码如下:
const rowChangeTasks = []
// 原来的代码,单行逐行填充
arrayValue.forEach((value, idx) => {
const changeSqls = changesql.split(';')
changeSqls.forEach(cSQL => {
const p = ((currentRow, currentRowIndex) => {
return new Promise((resolve, reject) => {
const _this = this
// this.selectedRow = table.tableFullData[theRowIndex + idx]
currentRow[columnName] = value
const sql = this.replaceAllParams(cSQL, { selectedRow: currentRow })
this.ExecCmd({ sql: sql, callName: '表格单元格change事件,执行存储过程', callMethod: 'tableCellDataChangeHandler' }).then(res => {
return this.getErrorData(res, 'subtable')
}).then(res => {
if (res && res.length) {
const rowData = Object.assign({}, res[0])
if (Object.prototype.hasOwnProperty.call(rowData, _this.keyname)) {
delete rowData[_this.keyname]
}
// rowData[this.keyname] = `-${idx + theRowIndex}`
const currentColumnObject = {}
currentColumnObject[columnName] = value
Object.assign(currentRow, currentColumnObject, rowData)
return table.cellDefaultValue(currentRow, currentRowIndex)
} else {
return Promise.resolve()
}
}).then(() => {
table.calcFormulasHandler(currentRow, columnName) // 计算公式
resolve()
}).catch(error => {
reject(error)
})
})
})(table.tableFullData[theRowIndex + idx], theRowIndex + idx)
rowChangeTasks.push(p)
})
if (idx) {
table.tableFullData[theRowIndex + idx][columnName] = value
}
})
this.common.doPromiseArray(rowChangeTasks).then(() => {
console.log('结束')
})
用了闭包,有效解决了这个问题。