0

I am currently exercising javascript by writing a chrome extension. In this process, I have repeatedly run into situations, where I

  • start out with a synchronous dummy-implementation
  • and notice later, that the intended final implementation needs to use asynchronous APIs.

For example I had an intermediate implementation for user-options,

function getOption(name){ 
    return INFO[name].default;
}

However, I want to add support for synchronization with chrome.storage.get/set, both of which are asynchronous. With promises, I can rewrite the function e.g. as

function getOption(name){
    return new Promise(function(resolve){
        chrome.storage.sync.get(name, resolve);
    }).then(function(obj){
        const val = obj[name];
        return val !== undefined ? val : INFO[name].default;
    });
}

However, this requires refactoring for explicit handling of the asynchronicity everywhere options are used, by either

  • Explicitly using the promise API
  • Converting the functions using options into async functions, such that await can be used, which in turn requires converting functions expecteing these to be synchronous to be rewritten, etc.

Alternatively, I could imagine some hackish solution, such as having a background function periodically synchronize the options, e.g.

function getOption(name){
    return INFO[name].actual !== undefined 
        ? INFO[name].actual : INFO[name].default;
}

// Sync once a minute
window.setInterval(function sync(){
    chrome.storage.sync.get('THENAME', function(obj){
        INFO[name].actual = obj.THENAME;
    },
    60*1000);

In this specific case it would be acceptable, but given my frustration with programs that use such a polling-based approach for synchrnozation I'd rather avoid it.

Is there some better method for handling such situations?

kdb
  • 4,098
  • 26
  • 49

1 Answers1

2

There isn't really. Refactoring from synchronous to asynchronous is a major change, sending tremors through the whole application. Using promises with async/await will have the lowest syntactic overhead, though.

The only way to avoid this is to design the whole application as asynchronous from the beginning. Make sure to consider concurrency (with possible race conditions) everywhere and enforce sequences where necessary. Realising that user options will at some point (in the future development process) have to be dynamically loaded at runtime from some storage (disk, network, whatever) - and not just at startup, where we could work around this -, start with an asynchronous prototype:

function getOption(name) { 
    return Promise.resolve(INFO[name].default);
}
// or
async function getOption(name) { 
    return INFO[name].default;
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375