gpt4 book ai didi

node.js - 使用 Bluebird Promises,如何通过延迟反模式解决这个问题?

转载 作者:太空宇宙 更新时间:2023-11-03 23:27:24 25 4
gpt4 key购买 nike

我正在学习 Bluebird Promise,并且我正在尝试学习不再使用任何 Deferred()。下面的代码运行 100% 正确且符合预期。但这对我来说是一个重构代码以正确使用 Bluebird Promise 的练习,而不是使用 Deferred 解决方案。我正在尝试学习以不同(正确)的方式思考 Promise,但经过多次尝试后,我仍然无法弄清楚如何在没有 Deferreds 的帮助下解决下面这个特定问题。

有人有想法吗?

运行方法如下:

1) 在控制台中运行此程序。它将启动一个使用端口 8080 的 Websocket 服务器。

2) 然后在另一个控制台窗口中再次运行它。在尝试使用端口 8080 失败 3 次后,该端口将启动并使用端口 8081。

// Initialization stuff
const WebSocket = require('ws');
var wsServer;

// Main Program
// =================================================================
tryCreateWebsocket().then(
function(){
console.log("Websocket succesfully initialized.");
},
function(){
console.log("Websocket startup has failed!");
}
);
// =================================================================



// Helper function: Creating a websocket, with a port as parameter
function createWebsocket(port){
return new Promise(function(resolve, reject){

wsServer = new WebSocket.Server({
perMessageDeflate: false,
port: port
});

wsServer.on("error", reject);
wsServer.on("listening", resolve);
});
}


// Main function: I try to create a websocket on 5 different ports with a resursive function
function tryCreateWebsocket(attempt, myMainDfd){

if(typeof attempt === "undefined"){
attempt = 1;
myMainDfd = deferred();
}

var ports = [8080, 8080, 8080, 8081, 8082]; // In the 2nd client, this should fail until port 8081
var curPort = ports[attempt - 1];

var maxAttempts = 5;


createWebsocket(curPort)
.then(
function(){
myMainDfd.resolve(); // Success
},
function(err){ // Error, retry
if(attempt != maxAttempts){
console.log("- attempt " + attempt + " failed. Retry");
tryCreateWebsocket(++attempt, myMainDfd);
}else{
myMainDfd.reject();
}
}
);

return myMainDfd.promise;
}


// Helper Function: I'm still using deferreds for now
function deferred() {
var resolve, reject;
var promise = new Promise(function() {
resolve = arguments[0];
reject = arguments[1];
});
return {
resolve: resolve,
reject: reject,
promise: promise
};
}

最佳答案

在 3 年的 Promise 编程中,我只发现一种情况,使用 deferred 使我的代码更简单。我得出的结论是,这是一种非常罕见的情况。通过学习正确的技术(此处使用链接),人们几乎总是可以避免它们,并最终得到更简单的代码,这些代码出现相当常见错误的风险更小(例如不完整的错误传播或未捕获的异常)。

在这种特殊情况下,您可以通过从 .then() 处理程序内部返回新的 Promise,将后续尝试链接到前一个 Promise。这允许您从连接函数返回一个 promise ,但保留该 promise 以用于 future 的尝试(推迟其最终解决方案),直到某些 future 的重试尝试成功或直到您用完重试尝试为止。

你可以这样做。特别注意 connect() 函数内部发生的情况。

function tryCreateWebsocket(){

var attempt = 1;
var ports = [8080, 8080, 8080, 8081, 8082];
var maxAttempts = ports.length;

function connect() {
var curPort = ports[attempt - 1];
return createWebsocket(curPort).catch(function(err){ // Error, retry
if(attempt < maxAttempts){
console.log("- attempt " + attempt + " failed. Retry");
++attempt;

// chain next attempt onto previous promise
return connect();
} else {
// reject here with no more retries
throw new Error("max retry attempts exceeded without successful connection");
}
});
}

// start trying to connect, return a promise
// errors will be caught and subsequent retries will be chained
// onto this first promise until it either succeeds or runs out
// of retry attempts
return connect();
}

// Main Program
// =================================================================
tryCreateWebsocket().then(function(wsServer){
console.log("Websocket succesfully initialized.");
// server instance is valid here, use it for further code
},function(){
console.log("Websocket startup has failed!");
});
// =================================================================



// Helper function: Creating a websocket, with a port as parameter
function createWebsocket(port){
return new Promise(function(resolve, reject){

wsServer = new WebSocket.Server({
perMessageDeflate: false,
port: port
});

wsServer.on("error", reject);
wsServer.on("listening", function() {
resolve(wsServer);
});
});
}

注意,我更改了设计,使 wsServer 实例成为返回的 Promise 的解析值。然后,您就不会依赖副作用来设置更高范围的变量。您可以从已解决的 promise 中获取它,并在您知道它有效时将其存储在您想要的位置。

关于node.js - 使用 Bluebird Promises,如何通过延迟反模式解决这个问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42218186/

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