停止执行进一步的代码



我有一个请求:

Character.count({'character.ownerid': msg.author.id}, function (err, count) {
if (err) {
throw err;
}
if (count > 3) {
err.message = 'Too many characters';
//create error explanation and throw it
throw err;
}
})

如果确实发生任何错误,我需要退出整个父函数。我无法在此请求中返回,因为它仅退出此方法。我认为有可能进行如下回调:

Character.count({'character.ownerid': msg.author.id}, function (err, count, stop) {

但是如何使用它呢?它位于匿名函数中,我不知道将其内容放在哪里。我也尝试使用try/catch但由于Error: Unhandled "error" event. ([object Object])而无法向外部处理程序抛出错误,请参见下面的代码:

Character.count({'character.ownerid': msg.author.id}, function (err, count) {
if (err) {
throw err;
}
if (count > 3) {
var err = {};
err.message = 'Too many characters';
throw err;
}
}).then((count) => {
console.log('all good we may continue');
console.log(count);
}).catch((err) => {
if (err != undefined && err.length > 0) {
msg.reply(err.message);
return 0; //exit parent function?
}
});

但即使这有效,我也不确定这段代码是否会满足我的需要。请求是异步的,那么如果其余代码在then之前被触发怎么办?这可能吗?

所以我基本上需要以某种方式return 0;父函数,如果有任何错误,我需要为它们提供一个处理程序。对此有什么想法吗?

你似乎错过了这个概念。首先,如前所述,所有猫鼬操作都返回一个 Promise 或至少一个"类似 Promise"的对象,该对象可以立即通过then()解决,而不是传入回调函数。这可以通过两种方式呈现。

使用async/await语法和try..catch块:

const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.set('debug', true);
mongoose.Promise = global.Promise;
const characterSchema = new Schema({
name: String
});
const Character = mongoose.model('Character', characterSchema);
const log = data => console.log(JSON.stringify(data,undefined,2));
const doCount = async () => {
let count = await Character.count();
if (count > 3)
throw new Error("too many charaters");
return count;
};

(async function() {
try {
const conn = await mongoose.connect(uri);
await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()))
await Character.insertMany(
["Huey","Duey","Louie"].map(name => ({ name }))
);
let count = await doCount();
log({ count });
await Character.create({ name: 'Donald' });
let newCount = await doCount();
console.log("never get here");

} catch(e) {
console.error(e)
} finally {
mongoose.disconnect();
}
})()

或者使用标准then()catch()语法:

const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost/test';
mongoose.set('debug', true);
mongoose.Promise = global.Promise;
const characterSchema = new Schema({
name: String
});
const Character = mongoose.model('Character', characterSchema);
const log = data => console.log(JSON.stringify(data,undefined,2));
function doCount() {
return Character.count()
.then(count =>  {
if (count > 3)
throw new Error("too many charaters");
return count;
});
};

(function() {
mongoose.connect(uri)
.then(conn => Promise.all(
Object.entries(conn.models).map(([k,m]) => m.remove())
))
.then(() => Character.insertMany(
["Huey","Duey","Louie"].map(name => ({ name }))
))
.then(() => doCount())
.then(count => log({ count }))
.then(() => Character.create({ name: 'Donald' }))
.then(() => doCount())
.then(() => console.log("never get here"))
.catch(e => console.error(e))
.then(() => mongoose.disconnect() );
})()

两个列表的输出完全相同:

Mongoose: characters.remove({}, {})
Mongoose: characters.insertMany([ { _id: 5b0f66ec5580010efc5d0602, name: 'Huey', __v: 0 }, { _id: 5b0f66ec5580010efc5d0603, name: 'Duey', __v: 0 }, { _id: 5b0f66ec5580010efc5d0604, name: 'Louie', __v: 0 } ], {})
Mongoose: characters.count({}, {})
{
"count": 3
}
Mongoose: characters.insertOne({ _id: ObjectId("5b0f66ec5580010efc5d0605"), name: 'Donald', __v: 0 })
Mongoose: characters.count({}, {})
Error: too many charaters
at doCount (/home/projects/characters/index.js:20:11)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)

如您所见,该函数愉快地返回其值,其中count保持为 3 或更低,但随后抛出一个异常,当count大于 3 时停止进一步执行,因为"never get here"消息永远不会被记录。

因此,这里不需要"回调",除非您将它包装在 Promise 中,否则您不会使用回调,无论如何都可以进行相同类型的错误处理。

但是,如果您有"错误",则throw错误。这在承诺链中工作正常,但是不作为承诺返回的"回调"根本不是该链的一部分,并且永远不会被"捕获"。因此,在不需要的时候不要使用回调。

只是为了踢球,用 Promise 包装回调会像这样完成:

function doCount() {
return new Promise((resolve,reject) =>
Character.count().exec((err,count) => {
if (count > 3)
reject(new Error("too many charaters"));
resolve(count);
})
);
};

但值得注意的是,考虑到本机方法返回的内容无论如何都可以作为 Promise 解析,因此没有必要。

相关内容

最新更新