如何在 javascript 中将绑定方法作为参数传递?

问题描述 投票:0回答:1

我试图将绑定方法传递给函数,但我不太明白语法。看起来 javascript 想要以某种方式区分未绑定方法和绑定方法,但是调用上下文会改变这一点。 (大多数编程语言只是将方法定义为绑定类函数)。

将绑定方法传递给函数,然后在新作用域中调用该绑定方法的语法是什么?

这是相关片段

const mongoose = require('mongoose');
const caching = require('../lib/caching')

const Blog = mongoose.model('Blog');

// This is where I'm trying to pass a method to another function. I'm unclear of the syntax here
Blog.find = caching.makeCachable(Blog.find.bind(Blog), Blog)

module.exports = app => {
  app.get('/api/blogs', requireLogin, async (req, res) => {
    let blogs = await Blog.find({_user: req.user.id});
    return res.send(blogs);
  });

  // ... other routes
}

缓存.js

const util = require('util');
const redis = require('redis');

const client = redis.createClient('redis://localhost:6379');
const asyncGet = util.promisify(client.get).bind(client);

const DEFAULT_CACHING = [
    'EX', 60 * 60 * 1,//caching expires after 4 hours
]

// This is where I take the method and pass it on to another function. I hope this just passes through
function makeCachable(method, thisObject) {
    console.log(method, thisObject, `${method.className}.${method.name}`);
    return cachedQuery.bind(method, `${thisObject.className}.${method.name}`);
}

async function cachedQuery(queryFunction, queryKey, queryParams=null, cacheConfig=DEFAULT_CACHING) {
    //check redis before executing queryFunction
    const redisKey = JSON.stringify([queryKey, queryParams]);
    const cacheValue = await asyncGet(redisKey);

    if(cacheValue) {
        return JSON.parse(cacheValue);
    }
    
    // This is where I try to call the bound method
    const blogs = await queryFunction.call(queryParams);
    
    if(blogs) {
        client.set(redisKey, JSON.stringify(blogs), ...cacheConfig);
    }

    return blogs;
}

exports.makeCachable = makeCachable;

编辑

显然我对什么不起作用还不够清楚。我的代码的这个版本是在尝试了几种不起作用的组合之后,但错误总是相似的。例如,如果我尝试调用

const blogs = await queryFunction(queryParams);
我会收到以下错误

[0] E:\Documents\Code\nodejs_class\AdvancedNodeStarter\lib\caching.js:23
[0]     const blogs = await queryFunction(queryParams);
[0]                         ^
[0]
[0] TypeError: queryFunction is not a function
[0]     at Function.cachedQuery (E:\Documents\Code\nodejs_class\AdvancedNodeStarter\lib\caching.js:23:25)
[0]     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
[0]     at async E:\Documents\Code\nodejs_class\AdvancedNodeStarter\routes\blogRoutes.js:22:17
[0]

同样,我尝试过,

Blog.find = caching.makeCachable(Blog.find);
Blog.find = caching.makeCachable(Blog.find.bind(Blog));
,我尝试过使用
.call()
和不使用
.call()
来调用。在所有情况下,我都会遇到类似上面的错误。

我对所有其他编程语言的期望(有一些细微的语法差异)是 Blog.find 一个绑定方法。例如,C++ 允许您分别引用

&Blog.find
&Model::find
来表示绑定/未绑定方法。 Python 允许您分别简单地引用
Blog.find
Model.find
来表示绑定/未绑定方法。

在某些情况下,javascript 似乎希望您显式绑定它。但无论出于何种原因,当我将函数(无论是否绑定)传递给 makeCachable 时,它似乎不再是一个函数。将绑定方法传递给另一个函数的实际语法是什么?是否需要做一些额外的事情才能将方法绑定到另一个函数参数?

javascript node.js
1个回答
0
投票

好吧,我仍然不知道为什么,但这里有一个解决方法。如果我只是将 makeCacheable 函数更改为使用闭包而不是显式调用绑定,它就可以工作

function makeCachable(method, thisObject) {
    queryKey = `${thisObject.className}.${method.name}`;
    return function(queryParams=null, cacheConfig=DEFAULT_CACHING) {
        return cachedQuery(method, queryKey, queryParams, cacheConfig);
    }
}

我没有解释为什么

return cachedQuery.bind(method, queryKey);
不起作用,但闭包确实起作用。

© www.soinside.com 2019 - 2024. All rights reserved.