gpt4 book ai didi

javascript - Node.js 中无错误时短路异步流的模式

转载 作者:太空宇宙 更新时间:2023-11-04 02:32:43 24 4
gpt4 key购买 nike

Node 使用 CPS 约定进行回调。通常,如果函数返回错误,做法是处理错误或通过执行诸如 return cb(err) 之类的操作将错误回调给您的父级。

我遇到的问题是,我经常需要短路路径,但实际上我本身并没有“错误”。是否有这样做的既定模式?

当使用异步进行流量控制时,此问题尤其经常出现。

这是一个例子:

var primaryFunction = function(arg1, cb) {
var template;
var data;
var result;

async.series([
function(cb) {
// load some data from different sources
async.parallel([
function(cb) {
fs.readFile("/somepath", function(err, temp) {
if (err) { return cb(err); }

template = temp;

cb(null);
});

},
function(cb) {
api.find({}, function(err, temp) {
if (err) { return cb(err); }

data = temp;

cb(null);
});

}
]
},
function(cb) {
// do a bunch more work

cb(null);
},
function(cb) {
// do a bunch more work

cb(null);
},
function(cb) {
// combine data and template
result = goatee.fill(template, data);

cb(null);
}
], function(err) {
if (err) { return cb(err); }

cb(null, result);
});
}

让我们想象一下,如果 api 没有返回任何文档,那么我想停止流控制,这样它就不会运行该大异步链的任何其余部分,但这并不完全是一个错误。这只是一个短路,所以也许我会在屏幕上显示一条友好的消息,这样可以节省一些处理周期。

以下是我考虑的一些选项:

  1. 传递一个非错误,例如 cb("halt"),然后在最终回调中检查 err instanceof Error。非空值会导致异步不运行其他系列。然后,在最后的回调中,我以一种方式处理“真正的”错误(将它们传递出去),并以我自己的方式处理“我的”错误。
  2. 我可以创建自己的错误类型,然后在最终回调中返回该类型和 err instanceof MyError。我听说创建错误的成本很高(当然比字符串或普通的旧 {} 更昂贵)。
  3. 我可以创建一个 next 风格的回调,但是系统不能很好地处理异步并且偏离 CPS 标准。
  4. 我可以使用 Promise,因为它们提供了带有成功回调和失败回调的双重回调理念,但我不是 Promise 的粉丝,因为它们不像 Node CPS 那样通用,而且有太多相互竞争的实现。
  5. 我可以设置一个变量来停止状态,但随后我必须检查异步链中每个函数中的停止变量。

现在,返回简单的字符串或简单的对象似乎是最好的,这同样适用于模块内通信,而不是到达模块外部的通信。该解决方案“感觉”很脏,但从技术上讲它是有效的。有什么想法吗?

最佳答案

我自己会使用选项 2。我会创建一个 HaltCondition 错误,如下所示:

function HaltCondition(reason) {
Error.call(this);
this.message = reason;
}
util.inherits(HaltCondition, Error);

然后,当我需要短路异步流程的其余部分时,将其用作回调中的错误参数。我知道您担心创建错误对象的费用,但根据我的经验,它可以忽略不计。

我进行了一个快速测试并对其进行了分析,以了解使用 HaltCondition 错误和仅返回 true 作为错误(如您的选项 1)之间有什么区别。

这是我使用的代码(类似于您问题中的代码):

var async = require('async'),
util = require('util');

function HaltCondition(reason) {
Error.call(this);
this.message = reason;
}
util.inherits(HaltCondition, Error);

async.series([
function(cb) {
async.parallel([
function(cb) {
setTimeout(function() {
cb(null, 'a');
}, 10);
},
function(cb) {
setTimeout(function() {
cb(null, 'b');
}, 20);
},
], cb)
},
function(cb) {
setTimeout(function() {
cb(new HaltCondition("test halt"), 'd');
}, 50);
},
function(cb) {
setTimeout(function() {
cb(null, 'e');
}, 30);
}
], function(err, result) {
if (err instanceof HaltCondition) {
console.log('HALTED:', err.message);
} else if (err) {
console.log('ERROR:', err.message);
} else {
console.log('DONE:', result)
}
});

我正在停止第二个系列函数中的异步流程。

当我仅使用 true 对其进行测试时,我替换了以下几行:

cb(new HaltCondition("测试停止"), 'd');cb(true, 'd');

和:

if (err instanceof HaltCondition) { with if (err === true) {

我使用node --profile在 Node v0.10.30中对其进行了分析,然后使用node-tick处理v8.log

  • 使用 HaltCondition 时,代码在 100 次运行中平均执行 93.2 次周期
  • 使用 true 时,代码在 100 次运行中平均执行 93.3 个周期

100 次运行中平均 0.1 个刻度的差异基本上不存在(而且很容易在误差范围内)。

关于javascript - Node.js 中无错误时短路异步流的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25147656/

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