我可以使用原型模式而不是闭包模式来创建解析为对象的承诺吗? [复制]

Posted

技术标签:

【中文标题】我可以使用原型模式而不是闭包模式来创建解析为对象的承诺吗? [复制]【英文标题】:Can I use the prototype pattern instead of the closure pattern to create promise that resolves to an object? [duplicate] 【发布时间】:2019-04-26 05:03:42 【问题描述】:

这是我的闭包,它创建了一个解析为对象的承诺:

function createConnection(host, port, timeout) 
    let latestTransactionId = 0;
    let commandResolvers = new Map();
    const socket = new WebSocket(`$host:$port`);

    function newTransactionId() 
        latestTransactionId += 1;
        return latestTransactionId.toString();
    

    function request(body) 
        return new Promise(function(resolve, reject) 
            const transactionId = newTransactionId();
            commandResolvers.set(transactionId, resolve);

            socket.send(JSON.stringify(
                ...body,
                trans_id: transactionId
            ));

            setTimeout(function () 
                reject(Error("Command timed out..."));
            , timeout);    
        );
    

    return new Promise(function(resolve, reject) 
        socket.onopen = function () 
            socket.onmessage = function(event) 
                const data = JSON.parse(event.data);
                const transactionId = data.trans_id;
                const commandResolver = commandResolvers.get(transactionId)
                commandResolver(data);
            ;

            connection = 
                request: request
            

            resolve(connection);
        ;

        setTimeout(function () 
            reject(Error("Connection timed out..."));
        , timeout);
    );

这是我的使用方法:

const connection = await createConnection(host, port, timeout);

我将如何重写对象创建实现以使这种语法成为可能:

const connection = await new Connection(host, port, timeout);

或者也许以下会更好

const connection = await new ConnectionPromise(host, port, timeout);

这有意义吗?我在理解什么时候应该使用闭包来创建对象以及什么时候应该使用原型时仍然存在一些问题。人们似乎也推荐了不同的模式,几乎没有实际的优点和缺点,但我更喜欢原型模式,所以更喜欢在这里使用它,这样做很有意义。

【问题讨论】:

如果您有多个要监听的套接字是有意义的。您是否有创建构造函数和原型的问题,或者这不是问题的一部分?关于闭包,它不是闭包和原型之间的选择。您可以根据需要混合和匹配它们,但是从您的措辞方式来看,我认为您可能是指单身人士?就像一个只能创建一个实例的对象?因为简单地说,闭包只是在使用时对函数及其数据进行包装。 因此,在您的代码中,调用 createConnection() 将围绕函数 createConnection 以及变量套接字、解析器等背后的数据创建一个闭包,以便在 createFunction() 运行完成后仍可以访问它们。 您可以尝试将套接字、解析器和 id 放在 request: request 对象上,并让request(以及newTransactionId)成为一个方法。然后使用构造函数创建该对象并为其提供原型方法。但是不,这不应该改变createConnection 的性质,它应该保持一个简单的函数(或最多是一个静态方法),它返回一个(实例)对象的承诺。 【参考方案1】:

你可以让你的构造函数返回一个承诺,..

例如。

class Connection 
  constructor ()     
    this.name = "connection";
    return new Promise((resolve) => 
      setTimeout(() => 
        this.name = "connection made";
        resolve(this);
      , 1000);
    );
  


async function test () 
  console.log("Start");
  const a = await new Connection();
  console.log(a.name);
  console.log("End");


test();

【讨论】:

谢谢!我会在星期一试试 No, don't do that! @Bergi 是的,我确定这不是一个好主意。但出于好奇,它如何与继承相混淆。为我执行 instanceof 返回 true,而不是您在链接中提到的 false,我还使用 extends 创建了一个子类,并且 Connection 和 Connection2 都为 instanceof 返回了 true。也做方法和覆盖似乎工作。这是使用 Chrome,所以我想知道这是否更像是 ES5 继承问题?我能找到的是是的,super 会返回一个承诺,但那不是预期的吗?方法this 仍然是实例。 另外,刚刚使用 Babel 将相同的测试编译到 ES5,instanceof 再次返回 true.. :( 我确定我遗漏了一些东西,因为根据过去的经验,我知道你知道你的东西.. :) 你能举一个简单的例子来展示梨形的东西吗? @Keith 我推荐class Connection constructor(name) this.name = name; static create() return new Promise(resolve => setTimeout(resolve, 1000, "connection made")).then(name => new Connection(name));

以上是关于我可以使用原型模式而不是闭包模式来创建解析为对象的承诺吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

原型模式

克隆原型设计模式的功能?

原型模式

原型模式——HeadFirst设计模式学习笔记

创建对象----原型模式

原型模式(Prototype Pattern)