Node JS中每个的顺序异步操作
Sequential async operations for each in Node JS
我正在进行数据库迁移。这需要查询一个数据库,获取一组记录并执行一组异步操作以将数据插入新数据库。为了保持数据的一致性,我想一次插入一条记录,所以我希望每个操作都按顺序 运行 。我发现执行这些操作的唯一方法是使用递归。
有没有更简洁的方法来做同样的事情?我知道有一个名为 async https://caolan.github.io/async/v3/ 的库,我以前从未尝试过。
我写的递归方法是这样的:
const insertItem = async (data) => {
let item = data[0];
if (!item) {
//I am done return
return;
}
try {
//Do multiple await calls to insert record into new database
} catch (e) {
//Recover from error (DB rollbacks, etc)
} finally {
//Remove inserted or failed item from collection.
data.shift();
await insertItem(data);
}
};
//Query original database
getInfo().then((data) => insertItem(data));
您可以使用同步循环for...of
它将等待 HTTP 响应。
const dataArr = ['data1', 'data2', 'data3'];
async function processItems(arr){
for(const el of arr) {
const response = await insertData(el);
// add some code here to process the response.
}
};
processItems(dataArr);
发布的代码通过使用 data.shift
在调用递归处理所有内容的单个函数之前改变参数数组,实现了对从第一个数据库检索的数据集合(数组)的迭代。
要清理它,通过将数据处理功能分成两部分来删除 shift
和递归调用:
- 一个函数来遍历从第一个数据库检索到的数据,
- 根据需要在第二个数据库中插入记录的第二个函数。
这消除了对 .finally
子句的需要,使代码结构看起来更像
async function insertData(data) {
for( let index = 0 ; index < data.length; ++index) {
await insertItem( data[index]);
}
}
async function insertItem( data) {
try {
//Do multiple await calls to insert record into new database
} catch (e) {
//Recover from error (DB rollbacks, etc)
// throwing an error here aborts the caller, insertData()
}
}
getInfo().then( insertData).catch( /*... handle fatal error ...*/);
根据偏好的风格,insertItem
可以声明为 insertData
中的嵌套函数以保持其整洁,并且 insertData
可以写成 insertData
的匿名函数参数=17=] 在 getInfo()
.
之后调用
当然,可以通过其他方式顺序执行异步操作,但在 async
函数中使用 await
可能是最简单的编码方法。
我正在进行数据库迁移。这需要查询一个数据库,获取一组记录并执行一组异步操作以将数据插入新数据库。为了保持数据的一致性,我想一次插入一条记录,所以我希望每个操作都按顺序 运行 。我发现执行这些操作的唯一方法是使用递归。
有没有更简洁的方法来做同样的事情?我知道有一个名为 async https://caolan.github.io/async/v3/ 的库,我以前从未尝试过。
我写的递归方法是这样的:
const insertItem = async (data) => {
let item = data[0];
if (!item) {
//I am done return
return;
}
try {
//Do multiple await calls to insert record into new database
} catch (e) {
//Recover from error (DB rollbacks, etc)
} finally {
//Remove inserted or failed item from collection.
data.shift();
await insertItem(data);
}
};
//Query original database
getInfo().then((data) => insertItem(data));
您可以使用同步循环for...of
它将等待 HTTP 响应。
const dataArr = ['data1', 'data2', 'data3'];
async function processItems(arr){
for(const el of arr) {
const response = await insertData(el);
// add some code here to process the response.
}
};
processItems(dataArr);
发布的代码通过使用 data.shift
在调用递归处理所有内容的单个函数之前改变参数数组,实现了对从第一个数据库检索的数据集合(数组)的迭代。
要清理它,通过将数据处理功能分成两部分来删除 shift
和递归调用:
- 一个函数来遍历从第一个数据库检索到的数据,
- 根据需要在第二个数据库中插入记录的第二个函数。
这消除了对 .finally
子句的需要,使代码结构看起来更像
async function insertData(data) {
for( let index = 0 ; index < data.length; ++index) {
await insertItem( data[index]);
}
}
async function insertItem( data) {
try {
//Do multiple await calls to insert record into new database
} catch (e) {
//Recover from error (DB rollbacks, etc)
// throwing an error here aborts the caller, insertData()
}
}
getInfo().then( insertData).catch( /*... handle fatal error ...*/);
根据偏好的风格,insertItem
可以声明为 insertData
中的嵌套函数以保持其整洁,并且 insertData
可以写成 insertData
的匿名函数参数=17=] 在 getInfo()
.
当然,可以通过其他方式顺序执行异步操作,但在 async
函数中使用 await
可能是最简单的编码方法。