“减少嵌套”;如果';s";在javascript中
我有三个异步运行的函数,其中返回函数是函数调用的一部分。我需要做的是“如果函数A和函数B返回一个好值(不是错误),那么就执行函数C。”我现在拥有的是“如果函数A返回一个好值,那么调用函数B,如果函数B返回一个好值,那么调用函数C。” 有没有更好的方法在javascript中实现这一点 我正在使用的代码如下:“减少嵌套”;如果';s";在javascript中,javascript,asynchronous,callback,Javascript,Asynchronous,Callback,我有三个异步运行的函数,其中返回函数是函数调用的一部分。我需要做的是“如果函数A和函数B返回一个好值(不是错误),那么就执行函数C。”我现在拥有的是“如果函数A返回一个好值,那么调用函数B,如果函数B返回一个好值,那么调用函数C。” 有没有更好的方法在javascript中实现这一点 我正在使用的代码如下: // Login to amazon // function 0 amazon.Login.authorize(options, function(authResponse)
// 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
}
}
}
您可以通过不将这些函数内联,而是在外部定义它们来降低复杂性。 在这个例子中 authorize(选项,authorizeCallback(响应))
等等,javascript将函数视为一等公民,因此您可以将它们视为值,并传递它们。正如Gustavo所演示的,您可以定义内联函数 在外面,然后参考它。 我建议你以这个为例 但这并没有减少嵌套条件。 当然,authorize函数看起来更短,但它始终包含嵌套的条件 如果嵌套条件越来越多,那么搜索关键字应该是“异步控制流模式”。然后你会发现库,它们解决了这个异步编码的地狱 看看异步库
看起来你在建造末日金字塔。您可以通过链接承诺来避免这种情况(我已经使用了来自的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的文档。也许这些方法已经有了回报承诺的版本
演示:对于初学者,如果您的
返回,则不需要使用else
,因为它保证是其他的。这里有一个关于使用promises
的不错的教程,只要您使用的是回调,这就是方法。您可以考虑使用命名函数,但本质上,这并不能帮助您得到通常称为“回调地狱”的东西。一种常见的替代方法是使用承诺,它提供了一种不同的链接调用的方法,但您仍然需要使用三个函数。“最佳”解决方案是使用async/await,但这只适用于ES7。此时,它是由一些编译成JavaScript的语言通过状态机模拟的。@BrianGlaz,你能看一下吗?嗨,Gustavo,使用这个解决方案,我仍然会调用函数a,然后调用函数a中的函数B,这是正确的吗?有没有一种方法可以处理你建议调用函数a,调用函数B,等待a和B的响应,如果两者都很好,是否继续?是的,我知道你正在尝试删除if/else,但仍然需要进行错误检查。处理大量回调的问题之一。我建议使用这种方法(代码不会杂乱无章,每个if/else都在一个单独的函数中)查看更新后的代码片段。第三种解决方案是Pubsub/Observer模式,但对于这个例子来说,这可能太多了。最佳方法是Gustavos解决方案。
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
});