在q(承诺)中,无法读取属性'apply'的undefined?

时间:2017-06-24 23:09:18

标签: node.js promise q

我尝试使用nodejs的q库,我使用Q.fcall然后出现以下错误。

file_path/node_modules/q.js:155
            throw e;
            ^
TypeError: Cannot read property 'apply' of undefined
at Promise.apply (/Users/name/Desktop/Programming/video_tutorial_archive/node_modules/q/q.js:1185:25)
at Promise.promise.promiseDispatch (/Users/name/Desktop/Programming/video_tutorial_archive/node_modules/q/q.js:808:41)
at /Users/name/Desktop/Programming/video_tutorial_archive/node_modules/q/q.js:1411:14
at runSingle (/Users/name/Desktop/Programming/video_tutorial_archive/node_modules/q/q.js:137:13)
at flush (/Users/name/Desktop/Programming/video_tutorial_archive/node_modules/q/q.js:125:13)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)

以下是我的代码:

app.get('/',function(req,res){

Q.fcall(sql_query.select_comment(con,comment))
.then(function(){

    var deferred=Q.defer();
    con.query("SELECT * FROM "+table_video, function (err, result) {
        console.log("step 2 finished");
        console.log("comment is "+comment);
            // if (err) throw err;
            query_result=result;
            // deferred.resolve();

        // console.log(query_result);
    })
    // return deferred.promise;

}).then(function(){
    console.log("step 3 finished");
    console.log("comment is "+comment);
    console.log(query_result);

    res.render('index',{
                result:query_result,
                comment:comment.comment
    });
}).done();

});

我可以用Q.defer解决它,但我想用fcall代替。它更干净,没有所有deferred.promise和deferred.resolve。

是什么导致错误“无法读取属性'应用'未定义”?以及如何解决它?

2 个答案:

答案 0 :(得分:2)

首先,你必须将一个函数传递给Q.fcall()。您正在传递sql_query.select_comment(con,comment)的返回结果,而这显然不是函数。

要使用Q.fcall()更正,您将第一个参数作为要调用的函数传递,并且以下参数是您要传递给该函数的参数。此外,如果您希望select_comment仍然绑定到sql_query(我不知道是否需要),那么您可以使用.bind()来保证安全。你可以像这样把所有这些放在一起:

Q.fcall(sql_query.select_comment.bind(sql_query), con, comment)

您获得的错误Cannot read property 'apply' of undefined是因为sql_query.select_comment()的返回值为undefined所以当Q.fcall()尝试在其上使用.apply()附加参数时,它会引发错误。

您还有另一个错误,即您的外部承诺不等待con.query("SELECT * FROM "+table_video, function (err, result) {})完成。最好的解决方案是只使用所有数据库功能的promise接口。然后,您可以从con.query()处理程序中返回.then()的承诺,它将自动链接到父承诺,事情将正确排序。

要亲自了解Q.fcall()内部的内容,您可以查看该功能的来源here on Github

Q.fcall = function (object /* ...args*/) {
    return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
};

这最终会尝试在.apply()的第一个参数上调用Q.fcall()

答案 1 :(得分:0)

我认为你应该将params分开:Q.fcall(sql_query.select_comment, con, comment),就像你对sql_query.select_comment.call(this, con, comment)

一样

找不到.apply(),因为sql_query.select_comment(con, comment)的返回值不是函数。