gpt4 book ai didi

callback - 外来控制流的 ES6 Promise 模式

转载 作者:行者123 更新时间:2023-12-04 23:47:51 25 4
gpt4 key购买 nike

ES6 Promise 很棒。到目前为止,调整我的想法很容易
回调成语。我发现它自然会鼓励更多的模块化代码,并且
当然错误处理更加清晰。

但是有几次我遇到了看起来(?)不像他们的心流情况
可以很容易地从 nodebacks 转换为 Promise(也许就是这样,但也许我只是对答案视而不见)。因为 promise 是不可知的
关于下一个操作(或者即使有一个),它似乎很难使用
带有 API 的 Promise 不仅接受回调,而且还返回它们。

想到的最常见的例子是“完成”回调。它出现在诸如数据库连接之类的东西中,表示“将连接返回到池”,但我也看到它在很多其他地方也出现了。

function getSomeStupidConnection(cb) {
var conn = /* ... */;
var iNeedToBeToldWhenIAmDone = function() { /* ... */ };

cb(conn, iNeedToBeToldWhenIAmDone);
}

getSomeStupidConnection(function(conn, done) {
/* ... */

conn.doLotsOfStuff(function(soMuchStuff) {

/* stuff! so much fun! */

/* okay conn go away I’m tired */

done();
});
});

像这样的逆流显然不是您希望在 API 中拥有的东西
首先,但它就在那里,有时你无法真正避免它。和
回调,您可以将“稍后调用”内部回调传递给原始“外部”
打回来。它并不完全导致关注点的完全分离,但在
至少它快速简单。

是否有适合这种情况的基于 Promise 的方法?一种说法,
“这是解析值——但是当链完成时,也要这样做”?一世
怀疑没有什么与我刚才描述的完全匹配,因为它
真的不可能说一个链条已经“完成”,但也许我错过了一些
模式让你接近那个而不会弄得一团糟......

编辑:根据目前的反馈,我意识到根本没有办法将这样的 API 包装在真正的 Promise 中,因为您返回的 Promise 将永远无法告诉您任何有关任何后续链式 Promise 的信息。但你可以伪造它。扭曲的是结果相当脆弱。它必须假设唯一的 then需要连接对象的是紧随其后的对象。 promise 的消费者需要了解它是一次性使用的连接,否则这并不明显。因此我在实践中并不真正推荐它,但为了好奇,这里有一个隐藏 done 的解决方案。同时表现为(并最终成为) promise 链:
/* jshint node: true, esnext: true */
'use strict';

// Assume this comes from an external library. It returns a connection and a
// callback to signal that you are finished with the connection.

function getConnectionExternal(cb) {
let connection = 'Received connection.';
let done = () => console.log('Done was called.');

cb(null, connection, done);
}

// Our promisey wrapper for the above

function getConnection() {
let _done;

let promise = new Promise((resolve, reject) => {
getConnectionExternal((err, connection, done) => {

if (err) return reject(err);

_done = (val) => {
done();
return val;
};

resolve(connection);
});
});

let _then = promise.then.bind(promise);

promise.then = (handler) => _then(handler).then(_done, _done);

return promise;
}

// Test it out

getConnection()
.then(connection => {
console.log(connection);

return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Finished using connection!');
resolve('This should be after connection closes.');
}, 200);
});
})
.then(msg => console.log(msg))
.catch(err => console.error(err));

控制台打印:
  • 收到连接。
  • 使用连接完成!
  • 完成被称为。
  • 这应该是在连接关闭之后。
  • 最佳答案

    详细说明 Bergi 的解决方案,这称为处置器模式。它以多种语言以多种形式存在 - with在 Python 中,using在 C# 和 try(){ 中使用 Java 中的资源。某些语言通过 C# 之类的析构函数以这种方式原生地处理作用域中的资源。

    一般的想法是使用一个范围来封装一个值的生命周期。在您的情况下是数据库连接。这比调用 done 要整洁得多。在回调中,因为更容易忘记调用 done留下一个开放的连接和资源泄漏。同步它看起来像:

    function scope(cb){
    try{
    var conn = getConnection(...);
    return cb(conn);
    } finally {
    conn.release();
    }
    }

    promise 版本并没有太大不同:
    function conn(data){
    var _connection;
    return getConnection().then(function(connection){
    _connection = connection; // keep a reference
    return data(_connection); // pass it to the function
    }).then(function(val){
    // release and forward
    _connection.release(); // if release is async - chain
    return val;
    }, function(err){
    _connection.release();
    throw err; // forward error
    });
    });

    哪个会使用:
    conn(function(db){
    return db.query("SELECT * FROM ...");
    }).then(function(result){ // handle result
    // connection is released here
    });

    关于callback - 外来控制流的 ES6 Promise 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28842886/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com