简体   繁体   中英

How to avoid redundant code in asynchronous javascript?

I'm rewriting some database code from synchronous (LocalStorage) to asynchronous (IndexedDB). I'm using the Alasql library and Promises. One of the problems I encounter is that when doing things asynchronously, sometimes it seems impossible to avoid duplicating code.

For example, my synchronous (pseudo) code could be something like this (idExists, doUpdate and doInsert are database methods):

function insertOrUpdate(data,id)
{
    var result = null;
    if (!idExists(id)) // idExists returns a boolean
        result = doInsert(data,id); // doInsert returns an object
    else
        result = doUpdate(data,id); // doUpdate returns an object
    doSomething(result);
}

With asynchronous code, it becomes something like this:

function insertOrUpdate(data,id)
{
    var promise1 = idExists(id); // idExists returns a promise
    promise1.then( function(id_exists) {
        if (id_exists) {
            var promise2 = doInsert(data,id); // doInsert returns a promise
            promise2.then( function(result) {
                doSomething(result);
            });
        }
        else {
            var promise3 = doUpdate(data,id); // doUpdate returns a promise
            promise3.then( function(result) {
                doSomething(result);
            });
        }
    });
}

Here I have to call doSomething at two places in the code. Is there a way to avoid this situation? I'm new to promises and my apologies if this has been asked before, but I couldn't find an answer to this.

You can return a promise from a chained callback, which then gets inserted into the promise chain. Your code can, and should, be written as:

function insertOrUpdate(data, id) {
    return idExists(id)
        .then(function (exists) {
            return exists ? doInsert(data, id) : doUpdate(data, id);
        })
        .then(doSomething);
}

The promises from doInsert or doUpdate will be chained into the existing chain from idExists , so the final .then(doSomething) will be executed with their result.

You can store promise into variable and call doSomething only once:

function insertOrUpdate(data, id) {
  return idExists(id).then(function(id_exists) {
    var promise = id_exists ? doInsert(data, id) : doUpdate(data, id)
    return promise.then(doSomething)
  });
}

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