gpt4 book ai didi

javascript - 如何同步运行嵌套的异步方法?

转载 作者:行者123 更新时间:2023-11-30 11:27:03 27 4
gpt4 key购买 nike

如何将此例程包装在 Promise 中,以便仅在获取所有数据时才解析?

var accounts = [];
getAccounts(userId, accs => {
accs.forEach(acc => {
getAccountTx(acc.id, tx => {
accounts.push({
'id': acc.id,
'tx': tx
});
});
})
});

编辑:如果我这样做有什么问题吗?

function getAccountsAllAtOnce() {

var accounts = [];
var required = 0;
var done = 0;

getAccounts(userId, accs => {
required = accs.length;
accs.forEach(acc => {
getAccountTx(acc.id, tx => {
accounts.push({
'id': acc.id,
'tx': tx
});

done = done + 1;
});
})
});

while(done < required) {
// wait
}

return accounts;
}

最佳答案

让我们把这个例程放到一个单独的函数中,这样以后更容易重用它。此函数应返回一个 promise ,该 promise 将通过帐户数组解决(我也会尽可能小地修改您的代码):

function getAccountsWithTx(userId) {
return new Promise((resolve, reject) => {
var accounts = [];
getAccounts(userId, accs => {
accs.forEach(acc => {
getAccountTx(acc.id, tx => {
accounts.push({
'id': acc.id,
'tx': tx
});
// resolve after we fetched all accounts
if (accs.length === accounts.length) {
resolve(accounts);
}
});
});
});
});
}

唯一的区别只是返回一个 promise 并在获取所有帐户后进行解析。然而,当你有很多嵌套的回调时,回调往往会使你的代码库具有这种“回调 hell ”的风格,并且很难对其进行推理。您可以使用良好的纪律来解决它,但是您可以大大简化它切换到从所有异步函数返回 promise 。例如,您的函数将如下所示:

function getAccountsWithTx(userId) {
getAccounts(userId)
.then(accs => {
const transformTx = acc => getAccountTx(acc.id)
.then(tx => ({ tx, id: acc.id }));

return Promise.all(accs.map(transformTx));
});
}

它们两者是绝对等价的,并且有大量的库可以“promisify”您当前的回调式函数(例如,bluebird 甚至原生 Node util.promisify)。此外,新的 async/await syntax它变得更加容易,因为它允许在同步流程中思考:

async function getAccountsWithTx(userId) {
const accs = await getUserAccounts(userId);

const transformTx = async (acc) => {
const tx = getAccountTx(acc.id);

return { tx, id: acc.id };
};

return Promise.all(accs.map(transformTx));
}

如您所见,我们消除了任何嵌套!它使对代码的推理变得更加容易,因为您可以在实际执行时阅读代码。但是,所有这三个选项都是等效的,因此您可以根据自己的项目和环境选择最有意义的选项。

关于javascript - 如何同步运行嵌套的异步方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47615542/

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