简体   繁体   中英

Refactoring nested if statements in JavaScript

I have a long series of nested if statements. The code I wrote works fine, but it is very unwieldy. Is there a simpler way to write this?

couchdb.query(phoneParam, function(err, data) {
    if (err) {
        console.log(err, err.stack);
    } else if (data.Items.length > 0) {
        deferred.resolve(data.Items[0]);
    } else {
        couchdb.query(phone1Param, function(err, data) {
            if (err) {
                console.log(err, err.stack);
            } else if (data.Items.length > 0) {
                deferred.resolve(data.Items[0]);
            } else {
                couchdb.query(phone2Param, function(err, data) {
                    if (err) {
                        console.log(err, err.stack);
                    } else if (data.Items.length > 0) {
                        deferred.resolve(data.Items[0]);
                    } else {
                        ...
                    }
                });
            }
        });
    }
});

You can replace the nested conditionals by writing a callback function that passes itself to couchdb.query if nothing interesting resulted from the query. To make the new query use the next phone parameter, increment a variable that acts as an index into an array of phone parameters.

The following code is logically equivalent to what you wrote above.

// Put all of your phone parameters into an array.
var phoneParams = [phoneParam, phone1Param, phone2Param, phone3Param]; 

// Use pos to track the array position of the current parameter.
var pos = 0;

function callback(err, data) {
    if (err) { 
        console.log(err, err.stack);
    } else if (data.Items.length > 0) { 
        deferred.resolve(data.Items[0]);
    } else if (++pos < phoneParams.length) {        // Increment the array position.
        couchdb.query(phoneParams[pos], callback);  // Recursive use of callback.
    }
}

// Kick off the series of calls.
couchdb.query(phoneParams[pos], callback);

It would probably be a good idea to check the value of pos afterward. If it's equal to phoneParams.length , you know that none of the phone parameters panned out, and you can do something about it. Where exactly would you put this code? You can't just insert it after the initial call to couchdb.query , because it's asynchronous and you don't know when the final callback is going to complete.

The solution is to continue your code in another function. You can call that function when you exit from callback without recursion. For example, if the function containing the clean-up code is called finish , you can modify callback thus:

function callback(err, data) {
    if (err) {                                // Print error and finish.
        console.log(err, err.stack);
        finish();
    } else if (data.Items.length > 0) {       // Use data and finish.
        deferred.resolve(data.Items[0]);
        finish();
    } else if (++pos < phoneParams.length) {  // Don't finish -- recurse.
        couchdb.query(phoneParams[pos], callback);
    } else {
      finish();                               // No choice but to finish.
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM