在javascript中减少嵌套的“if's”

时间:2015-06-05 13:31:19

标签: javascript asynchronous callback

我有三个异步运行的函数,其中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
          }
     }
}

3 个答案:

答案 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的文档。也许这些方法的版本已经返回了承诺。

演示:http://jsbin.com/tovokarole/1/edit?js,console

答案 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)

如古斯塔夫所示,你可以定义内联函数 在外面然后参考它。 我建议你这样做。

但这不会减少嵌套条件。 当然,授权函数看起来更短,但它内部始终存在嵌套条件。

如果你有越来越多的嵌套条件,那么你的搜索关键字应该是'异步控制流模式'。然后你会找到解决这个异步编码地狱的库。

看一下异步库。

https://github.com/caolan/async