如何同步运行嵌套的异步方法?
如何将此例程封装在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;
}
回答:
让我们把这个例程放到一个单独的函数中,以便稍后重用它。该函数返回一个承诺,这将账户的阵列来解决(我也将修改你的代码尽可能小):
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。例如您的FUNC看起来像下面这样:
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));
});
}
他们两人都是绝对的等同,而且有plently库来“promisify”您当前的回调风格的功能(例如,bluebird甚至本地节点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));
}
正如你所看到的,我们排除任何嵌套!它使得代码的推理变得更容易,因为你可以读取代码,因为它将被实际执行。但是,所有这三个选项都是相同的,所以这取决于您,在您的项目和环境中最有意义。
回答:
我会将每一步分成它自己的函数,然后从每一个函数返回一个promise或promise数组。例如,getAccounts变为:
function getAccountsAndReturnPromise(userId) { return new Promise((resolve, reject) => {
getAccounts(userId, accounts => {
return resolve(accounts);
});
});
};
而且getAccountTx解析为{ID,TX}对象数组:
function getAccountTransactionsAndReturnPromise(accountId) { return new Promise((resolve, reject) => {
getAccountTx(account.id, (transactions) => {
var accountWithTransactions = {
id: account.id,
transactions
};
return resolve(accountWithTransactions);
});
});
};
然后你可以使用Promise.all()
和map()
来解决最后一步数组以您想要的格式输入数值:
function getDataForUser(userId) { return getAccountsAndReturnPromise(userId)
.then(accounts=>{
var accountTransactionPromises = accounts.map(account =>
getAccountTransactionsAndReturnPromise(account.id)
);
return Promise.all(accountTransactionPromises);
})
.then(allAccountsWithTransactions => {
return allAccountsWithTransactions.map(account =>{
return {
id: account.id,
tx: tx
}
});
});
}
以上是 如何同步运行嵌套的异步方法? 的全部内容, 来源链接: utcz.com/qa/259602.html