gpt4 book ai didi

javascript - 用传递的结果重构 promise 级联

转载 作者:行者123 更新时间:2023-11-30 11:31:33 26 4
gpt4 key购买 nike

我正在为运行 docker 堆栈和容器的 Node CLI 创建初稿。

每次调用都是使用 docker 命令进行的,具有异步调用和结果。所以我们决定使用 promise 。

我们现在的主要问题是著名的 then 级联,尤其是当我们必须沿途传递值并启动微调器/消息时。

这是我们主要的丑陋方法。我试图弄清楚如何重构它以使其更具...可读性!

upgradeServiceImage({env, stack, service}) {
if (!env || !stack || !service) {
throw Error(`You must specify env, stack and service to upgrade a service`);
}

let payloadSpinner = ora({
text: `Getting upgrade payload. Please wait...`
}).start();

this.getServiceUpgradePayload({env, stack, service})
.then((response) => {
payloadSpinner.succeed(`Upgrade payload retrieved successfuly for service ${stack} > ${service}`);

let upgradeSpinner = ora({
text: `Upgrading the service. Please wait...`
}).start();

this.upgradeImage(response)
.then((res) => {
upgradeSpinner.succeed(`Image upgrade request for service "${service}" was made.`);

this.checkUpgrade({env, stack, service}).then((res) => {
let finishUpgradeSpinner = ora({
text: `Finishing upgrade of service by deleting old container. Please wait...`
}).start();

this.finishUpgrade(response).then(() => {
finishUpgradeSpinner.succeed(`Upgrade is now complete!`);
})
.catch((err) => {
finishUpgradeSpinner.fail(`Finishing upgrade failed. Please see in UI. Err: ${err}`);
})
})
.catch((err) => {
upgradeSpinner.fail(`${err}`);
})

})
.catch((err) => {
upgradeSpinner.fail(`Image upgrade failed with error: ${err}`);
});
})
.catch((err) => {
payloadSpinner.fail(err);
});
};

它工作完美,但几乎不可读且模块化。

我尝试使用 Promise.all 进行一些修复,但我在正确恢复微调器(加载消息)时遇到了问题,而且我无法将对象从一个 promise 传递到另一个 promise (例如:response) .

最佳答案

给定这样的代码:

let payloadSpinner = ora({
text:
}).start();

this.getServiceUpgradePayload({env, stack, service})
.then((response) => {
payloadSpinner.succeed(`Upgrade payload retrieved successfuly for service ${stack} > ${service}`);
// start the second task
})
.catch((err) => {
payloadSpinner.fail(err);
});

您可以使用为您管理微调器的助手重写它:

function withSpinner({ task, textOnStart, textOnSuccess, textOnError }) {
const spinner = ora({
text: textOnStart,
})
return task.then(value => {
spinner.succeed(textOnSuccess(value));
return result;
}, reason => {
spinner.fail(reason);
return Promise.reject(reason);
});
}

upgradeServiceImage({env, stack, service}) {
if (!env || !stack || !service) {
throw Error(`You must specify env, stack and service to upgrade a service`);
}

withSpinner({
task: this.getServiceUpgradePayload({env, stack, service}),
textOnStart: `Getting upgrade payload. Please wait...`,
textOnSuccess: result => `Upgrade payload retrieved successfuly for service ${stack} > ${service}`,
textOnError: error => error,
}).then(result => {
// start the second task
})

然后您可以重新使用帮助程序为后续步骤创建微调器。

请注意 withSpinner 返回的 promise 被拒绝,因此如果第一个任务失败,第二个任务将不会执行。

这是一个工作演示:

/* some scaffolding for the purpose of the example */

let spinnerId = 0;

function ora({ text }) {
let myId = spinnerId++;
console.log("Spinner", myId, "start", text);
return {
succeed(msg) {
console.log("Spinner", myId, "succeed", msg);
},
fail(msg) {
console.log("Spinner", myId, "fail", msg);
}
};
}

function delay(ms, result) {
return new Promise(resolve => setTimeout(() => resolve(result), ms));
}
function delayFail(ms, reason) {
return new Promise((resolve, reject) => setTimeout(() => reject(reason), ms));
}

/* scaffolding ends, actual code begins */

function withSpinner({ task, textOnStart, textOnSuccess, textOnError }) {
const spinner = ora({
text: textOnStart,
})
return task.then(value => {
spinner.succeed(textOnSuccess(value));
return value;
}, reason => {
spinner.fail(reason);
return Promise.reject(reason);
});
}

function upgradeServiceImage() {
return withSpinner({
task: delay(500, "THE UPGRADE PAYLOAD"),
textOnStart: `Getting upgrade payload. Please wait...`,
textOnSuccess: result => `Upgrade payload retrieved successfuly: ${result}`,
textOnError: error => error,
}).then(result => {
return withSpinner({
task: delay(800, "upgradeImage"),
textOnStart: `Upgrading the service. Please wait...`,
textOnSuccess: result => `Image upgrade request for service was made.`,
textOnError: error => error,
});
}).then(result => {
return withSpinner({
task: delayFail(700, "some kind of error"),
textOnStart: `Checking upgrade`,
textOnSuccess: result => `Checking upgrade finished`,
textOnError: error => `CHecking upgrade failed because ${error}`,
});
}).then(result => {
console.log("this won't run anymore because previous step failed");
}).catch(error => {
// additionally log the error if you want
console.error("catch", error);
});
};

upgradeServiceImage();

更新:这是使用 async/await 时相同代码的样子。只有 upgradeServiceImage 功能已被修改。这种方法更“扁平”和可读。这也使得在连续任务中使用以前的结果变得简单。

/* some scaffolding for the purpose of the example */

let spinnerId = 0;

function ora({ text }) {
let myId = spinnerId++;
console.log("Spinner", myId, "start", text);
return {
succeed(msg) {
console.log("Spinner", myId, "succeed", msg);
},
fail(msg) {
console.log("Spinner", myId, "fail", msg);
}
};
}

function delay(ms, result) {
return new Promise(resolve => setTimeout(() => resolve(result), ms));
}
function delayFail(ms, reason) {
return new Promise((resolve, reject) => setTimeout(() => reject(reason), ms));
}

/* scaffolding ends, actual code begins */

function withSpinner({ task, textOnStart, textOnSuccess, textOnError }) {
const spinner = ora({
text: textOnStart,
})
return task.then(value => {
spinner.succeed(textOnSuccess(value));
return value;
}, reason => {
spinner.fail(reason);
return Promise.reject(reason);
});
}

async function upgradeServiceImage() {
try {
const upgradeResult = await withSpinner({
task: delay(500, "THE UPGRADE PAYLOAD"),
textOnStart: `Getting upgrade payload. Please wait...`,
textOnSuccess: result => `Upgrade payload retrieved successfuly: ${result}`,
textOnError: error => error,
});
const upgradeImageResult = await withSpinner({
task: delay(800, "upgradeImage"),
textOnStart: `Upgrading the service. Please wait...`,
textOnSuccess: result => `Image upgrade request for service was made.`,
textOnError: error => error,
});
const anotherResult = await withSpinner({
task: delayFail(700, "some kind of error"),
textOnStart: `Checking upgrade`,
textOnSuccess: result => `Checking upgrade finished`,
textOnError: error => `CHecking upgrade failed because ${error}`,
});
console.log("this won't run anymore because previous step failed");
} catch (error) {
// additionally log the error if you want
console.error("catch", error);
};
};

upgradeServiceImage();

关于javascript - 用传递的结果重构 promise 级联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46073194/

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