简体   繁体   中英

Is there a way to check if a JavaScript function accepts a callback?

I am trying to add localForage support to the pure-form Web Component by creating a global instance of localForage:

// create a global appStorage object that mimics localStorage API (greater storage)
window.appStorage = localforage.createInstance({
    driver: [
        localforage.INDEXEDDB,
        localforage.WEBSQL,
        localforage.LOCALSTORAGE
    ],
    name: 'product-name',
    version: 1.0,
    storeName: 'app'
});

And assigning it to an instance of pure-form via the storage attribute:

<pure-form src="path-to-schema.json" storage="appStorage"></pure-form>

Internally, pure-form executes window[self.storage] to get a handle to the storage object and uses .getItem , .setItem to set and retrieve values synchronously.

Trouble is localForage is asynchronous, meaning .getItem , .setItem expect to return values via a callback. Therefore my current logic won't work:

// get value from web storage
var storedContent = window[self.storage].getItem('item-key');

I realise I could wrap the call in a Promise, but as it stands pure-form does not require promises and I'd hate to add that dependency just for this.

What I would like to do is check if .getItem or .setItem require a callback, and if so, modify the code accordingly...

As @Dave-Newton pointed out in the comments:

there's no way to tell without looking at the source or docs. That said, almost any async call either takes a callback or uses promises.

Based on that, I created two functions that wrap calls to .getItem and .setItem and inspects their responses. If they return an instance of Promise , it resolves using .then - otherwise executes the callback as normal:

/**
 * Get a value from web storage regardless of whether it's sync or async
 */
function getStorageItem(storage, key, callback) {

    if (typeof callback !== 'function') throw new Error('Invalid callback handler');

    var result = storage.getItem(key);

    if (result instanceof window.Promise) {
        result.then(callback);
    }
    else {
        callback(result);
    }
}

/**
 * Set a value in web storage regardless of whether it's sync or async
 */
function setStorageItem(storage, key, value, callback) {

    var result = storage.setItem(key, value);

    if (result instanceof window.Promise && callback) {
        result.then(callback);
    }
    else if (callback) {
        callback();
    }
}

Which means I can now do:

// get value from web storage
getStorageItem(webStorage, key, function(value) {

    if (value) {
        // whatever I want with the value
    }
});

Implementation here

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