有没有一种方法可以检查 JavaScript 函数是否接受回调函数?

3

我正在尝试通过创建localForage的全局实例,将localForage支持添加到pure-form Web组件中:

// 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'
});

将其分配给通过 storage 属性的 pure-form 实例:

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

在内部,pure-form执行window[self.storage]以获取存储对象的句柄,并使用.getItem.setItem同步设置和检索值。

问题是localForage是异步的,这意味着.getItem.setItem希望通过回调返回值。因此,我的当前逻辑将无法工作:

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

我知道我可以用Promise来包装这个调用,但目前pure-form不需要Promise,我不想为此添加依赖关系。
我的想法是检查.getItem或.setItem是否需要回调,如果需要,则相应地修改代码...

2
你需要查看文档,否则无法确定。不过,几乎所有的异步调用都会使用回调或者 Promise。 - Dave Newton
那么我猜另一种选择就是尝试确定存储是否是localForage的实例?问题在于,这将成为一个硬编码的边缘情况。 - John Doherty
1
@trincot 我不确定你的意思是什么? - John Doherty
1
函数具有长度属性,它指定了函数预期的参数数量。如果它需要回调,那么它需要比没有回调时多一个参数。但是,必须小心,因为函数声明不需要指定任何参数,而可以使用arguments变量处理。在这种情况下,length为零。或者它可能是混合的... - trincot
@Bergi 我是维护者之一,所以直接将更改应用到了代码仓库中… pure-form在许多商业混合移动应用中被使用,这些应用不支持promises。这意味着对它们的任何更新都会强制它们引入Promise polyfill。值得注意的是,pure-form是一种封装的网络组件,您可以像操作常规HTML标签一样与其交互,通过设置属性和监听事件。它不暴露任何回调/ promises。 - John Doherty
显示剩余6条评论
1个回答

5

正如评论中 @Dave-Newton 指出的:

没有办法在不查看源代码或文档的情况下确定。话虽如此,几乎所有异步调用都要么采用回调函数,要么使用 Promise。

基于此,我创建了两个函数来包装对 .getItem.setItem 的调用并检查它们的响应。如果它们返回一个 Promise 实例,它会使用 .then 解析 - 否则像往常一样执行回调函数:

/**
 * 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();
    }
}

这意味着我现在可以做到:

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接