等待异步函数完成而不添加回调

Wait for asynchronous function to finish without adding callback

本文关键字:添加 回调 异步 函数 等待      更新时间:2023-09-26

我正在使用Mocha和Should.js为我的Node.js/Express/Mongoose项目编写测试,并测试访问我的MongoDB的函数。我希望这些测试与数据库中的实际记录完全独立,所以我想创建一个条目,然后加载它,对它进行所有测试,然后删除它。我已经编写了实际的函数(我在整个项目完成后编写测试),这样create函数就没有回调;它只是在完成后呈现一个页面。在我的测试脚本中,我在调用create之后调用load_entry函数,但有时create的时间比平时长,因此load_entry在无法实际加载文章时会抛出错误,因为文章尚未创建。有没有什么方法可以确保异步函数在不使用回调的情况下完成?

如果我能提供更多信息,请告诉我。我搜索了谷歌,没有找到任何真正能回答我问题的东西,因为大多数解决方案都只说"使用回调!"

使用所谓的promise

您可以在此处阅读有关它的更多信息。

有很多很棒的图书馆可以为你做这件事。

Q.js是我个人喜欢的一个,现在它被广泛使用。承诺也存在于jQuery和许多其他中。

下面是一个在异步json-p调用中使用q promise的示例:DEMO

var time;
$.ajax({
    dataType: 'jsonp',
    type: 'GET',
    url: "http://www.timeapi.org/utc/now.json",
    success: function (data) {
        time = data;
    },
    error: function (data) {
        console.log("failed");
    }
})
.then(function(){ // use a promise library to make sure we synchronize off the jsonp
    console.log(time);    
});

这绝对是您想要回调的事情。除此之外,您将不得不编写某种回调包装器,它轮询数据库以确定数据库何时完成相关记录的创建,然后发出事件或执行其他异步操作以允许测试继续进行。

由于执行异步操作的唯一本地方法是:setTimeoutsetIntervaladdEventListener,并且它们都接受回调,因此您最终将不得不在某个地方使用回调。

但是,您可以使用Promise/A(也称为Deferred)来隐藏这一点。

你的代码可能是这样的:

db.create_entry("foo", data).done(function (entry) {
    db.delete_entry(entry).done(function () {
        console.log("entry is deleted");
    });
});

使用然后链接:

db.create_entry("foo", data).then(function (entry) {
    return db.delete_entry(entry);
}).done(function () {
    console.log("entry is deleted");
});;

我找到了一个有效的解决方案。我所做的是向我的函数(next)添加一个回调,并且只在指定的情况下调用它(即,用于测试):

//more stuff above
article.save(function(err){
    if (!err) {
        console.log(req.user.username + ' wrote ' + article.slug)
        return next() || res.redirect('/admin')
    }
    return next(err) || res.render('articles/entry_form', {
        title: 'New Entry',
        article: article,
    })
})

这样,当我运行实际的服务器并且没有指定回调时,它不会抛出错误,因为它只会返回res.render语句。