我有三个异步运行的函数,其中return函数是函数调用的一部分。我需要做的是“如果函数A和函数B返回一个好的值(不是错误),那么执行函数C.”我现在所拥有的是“如果函数A返回一个好的值,那么调用函数B,如果函数B返回一个好的值,则调用函数C.”
在javascript中有更好的方法吗?
我正在使用的代码如下:
// Login to amazon
// function 0
amazon.Login.authorize(options, function(authResponse) {
if ( authResponse.error ) {
// user not logged in. Do nothing.
alert('oauth error ' + response.error);
return;
}
else
{ // good response
// Call function A
amazon.Login.retrieveProfile(authResponse.access_token, function(response) {
if ( response.success ) { // good response
// Prepare to call function B
// Initialize the Amazon Cognito credentials provider
AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'abc' });
AWS.config.region = 'us-east-1';
AWS.config.credentials.params.Logins = { 'www.amazon.com': authResponse.access_token };
// Call function B. This could be called at the same time as function A
AWS.config.credentials.get(function(err) {
if (!err) {
// Both Function A and Function B came back with good results.
// Now can call function C and do more work
} else {
// error in function B
}
} else {
// error in function A
}
}
}
答案 0 :(得分:1)
看起来你正在建造金字塔末日。你可以通过链接承诺来避免这种情况(我使用了来自https://www.promisejs.org/的polyfill)。您可以根据需要链接任意数量的函数,只要它们返回承诺即可。此外,您可以避免else
阻止字节提前抛出异常。
var accessToken;
(new Promise(amazon.Login.authorize.bind(amazon.Login, options)))
.then(function (authResponse) {
if (authResponse.error) throw res.error;
accessToken = authResponse.access_token;
return new Promise(amazon.Login.retrieveProfile.bind(amazon.Login, accessToken));
})
.then(function (response) {
if (!response.success) throw 'Profile retrieval failed';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'abc' });
AWS.config.region = 'us-east-1';
AWS.config.credentials.params.Logins = { 'www.amazon.com': accessToken };
return new Promise(AWS.config.credentials.get.bind(AWS.config.credentials));
})
.then(function (err) {
if (err) throw err;
// call function C here
})
.catch(function (err) {
// do something with error
});
您可能需要查看有关所用API的文档。也许这些方法的版本已经返回了承诺。
答案 1 :(得分:0)
您可以通过不将这些函数内联,而是在外部定义它们来降低复杂性。 在这个例子中 amazon.Login.authorize(options,authorizeCallback(response));
function authorizeCallback(response) {
if ( authResponse.error ) {
alert('oauth error ' + response.error);
return;
}
amazon.Login.retrieveProfile(authResponse.access_token, retrieveProfileCallback);
}
function retrieveProfileCallback(response) {
if ( response.success ) { // good response
// Prepare to call function B
// Initialize the Amazon Cognito credentials provider
AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'abc' });
AWS.config.region = 'us-east-1';
AWS.config.credentials.params.Logins = { 'www.amazon.com': authResponse.access_token };
// Call function B. This could be called at the same time as function A
AWS.config.credentials.get(getCredentialCallback);
} else {
// error in function A
}
}
function getCredentialCallback(err) {
if (!err) {
// Both Function A and Function B came back with good results.
// Now can call function C and do more work
} else {
// error in function B
}
}
依此类推,javascript将函数视为一等公民,因此您可以将它们视为值,并传递它们。
答案 2 :(得分:0)
但这不会减少嵌套条件。 当然,授权函数看起来更短,但它内部始终存在嵌套条件。
如果你有越来越多的嵌套条件,那么你的搜索关键字应该是'异步控制流模式'。然后你会找到解决这个异步编码地狱的库。
看一下异步库。