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

如何将此例程封装在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

回到顶部