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

时间:2013-08-09 15:39:43

标签: javascript node.js asynchronous express mocha

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

如果我能提供更多信息,请告诉我。我看了整个谷歌,找不到任何真正回答我问题的东西,因为大多数解决方案只是说“使用回调!”

4 个答案:

答案 0 :(得分:5)

使用所谓的promise

您可以阅读更多相关信息 here

有许多优秀的图书馆可以为您做到这一点。

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

以下是使用q promise进行异步json-p调用的示例: 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);    
});

答案 1 :(得分:1)

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

答案 2 :(得分:0)

由于执行异步操作的唯一原生方式是:setTimeoutsetIntervaladdEventListener,并且它们都会进行回调,最终您必须在某处使用回调。

但是,您可以使用Promises / A隐藏它,也称为Deferreds。

您的代码可能如下所示:

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

使用then-chaining:

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

答案 3 :(得分:0)

我找到了一个有效的解决方案。我所做的是为我的函数(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语句。