蓝鸟承诺变量:'undefined不是函数'

时间:2016-07-23 14:51:06

标签: javascript node.js promise bluebird

我有一个nodejs express服务器,我正在使用bluebird Promises来同步所有异步内容。

使用AWS RDS MySQL数据库在localhost上一切正常,但当我将服务器上传到我的AWS EC2实例时,我发现此功能有问题:

DataTable dt = new DataTable();
mySqlDataAdapter.Fill(dt);
int socot = dt.Rows.Count;
for (int i = 0; i < socot; i++)
{
    String dn = dt.Rows[i][1].ToString();
    String gduan = "SELECT tennha FROM duannha WHERE id=@id";
    MySqlCommand cmd = new MySqlCommand();
    cmd.Connection = conn;
    cmd.CommandText = gduan;
    cmd.Parameters.AddWithValue("@id", dn);
    String gtennha = cmd.ExecuteScalar().ToString();
    dt.Rows[i][1] = gtennha;
}

我已将变量 findValue 声明为新的Promise,因为根据if条件,它将接收不同数据库查询函数的值(此函数返回Promise)。

当我调用此函数时,结果如下:“undefined is is a function”

我理解这种行为的发生是因为它首先执行var Promise = require('bluebird'); var db = require('./db'); exports.matchValue = function (params) { return new Promise(function(resolve, reject) { var findValue = new Promise(); if (params.find.includes(".")) { var aux = params.find.split("."); var matchBy = {}; if (aux[0]) matchBy.a = aux[0]; if (aux[1]) matchBy.b = aux[1]; findValue = db.getValues1(params.limit,params.page,matchBy); } else { findValue = db.getValues2(params.limit,params.page,params.find); } findValue .then(function(result) { resolve(result); }) .catch(function(err) { reject(err); }); }); } 而不是findValue.then()块代码,并且因为变量是未定义的,所以它可以是一个函数。

我认为将变量声明为新的Promise,它会等到分配给此变量的函数返回完成,但实际上并没有发生。

我做错了什么?有人能帮我吗?

谢谢你的建议!!

4 个答案:

答案 0 :(得分:0)

  

我已将变量findValue声明为新的Promise,因为根据if条件,它将接收不同数据库查询函数的值(此函数返回Promise)。

在JavaScript中,您不会将变量声明为任何类型。这一行:

var findValue = new Promise();

声明一个变量(var findValue)并尝试创建一个promise(= new Promise())。 Promise构造函数要求您将其传递给函数。它试图将其第一个参数用作函数,并且由于您没有传递任何参数,因此第一个参数得到undefined - 因此错误。

可以将其更改为

var findValue;

...但是您的代码正在成为不必要的承诺创建谬误的牺牲品:只需使用您已有的承诺:

exports.matchValue = function (params) {
    var findValue;
    if (params.find.includes(".")) {
        var aux = params.find.split(".");
        var matchBy = {};
        if (aux[0]) matchBy.a = aux[0];
        if (aux[1]) matchBy.b = aux[1];
        findValue = db.getValues1(params.limit,params.page,matchBy);
    }
    else {
        findValue = db.getValues2(params.limit,params.page,params.find);
    }
    return findValue;
}

答案 1 :(得分:0)

假设您的db.getValues1 / db.getValues2函数返回promises(它们似乎没有回调,我拒绝假设您在生产中使用同步DB驱动程序),请尝试以下版本您发布的代码:

var Promise = require('bluebird');
var db      = require('./db');

exports.matchValue = function (params) {
    var findValue;

    if (params.find.includes(".")) {
        var aux = params.find.split(".");
        var matchBy = {};
        if (aux[0]) matchBy.a = aux[0];
        if (aux[1]) matchBy.b = aux[1];
        findValue = db.getValues1(params.limit,params.page,matchBy);
    }
    else {
        findValue = db.getValues2(params.limit,params.page,params.find);
    }

    return findValue;
}

如果有效,那很好。以下是一些需要考虑的事项:

  1. 您正在创建一个新的Promise。不要那样做。使用Bluebird的promisification例程来宣传标准的,符合节点的函数/库。

  2. Bluebird 2.x和3.x会抛出var findValue = new Promise()。正如已经指出的那样,构造函数需要一个函数作为其参数。我怀疑你转述了你实际得到的错误信息。如果是这样,不要这样做,这使得其他人很难弄清楚出了什么问题。

  3. 下次发布到SO时,请将示例代码缩减为任何人都可以运行的内容并轻松重现您的问题。您可能会在找到最小的复制品的过程中发现您解决自己的问题。如果你不这样做,它将使这里的人们能够更有效地帮助你。

答案 2 :(得分:0)

我遇到了类似的问题,碰巧我也在使用Sequelize。

这里是重现问题的单线:

Promise.resolve({ a: 1 }).then(([x]) => {});

输出:

未处理的拒绝TypeError:未定义不是函数

此错误的原因是JavaScript试图对解析后的值执行[Symbol.iterator](),但是由于它是一个对象,因此在其中没有[Symbol.iterator]-undefined错误消息是value[Symbol.iterator]

更好的错误消息应该是value is not iterable行中的内容。

关于您为什么会这样,这一定是Sequelize的一个错误。如果您仍然遇到问题,请提出问题。

答案 3 :(得分:-1)

您的.matchValue()功能应简化为:

exports.matchValue = function(params) {
    var aux = params.find.split('.');
    return (aux.length < 2) ? db.getValues2(params.limit, params.page, params.find) : db.getValues1(params.limit, params.page, { 'a': aux[0], 'b': aux[1] });
};

有了这个,.then(function(result)肯定不会因为该线已经消失而被抛出,但函数的调用者可能会抛出。如果是这样,那么您必须(再次)怀疑db.getValues1()db.getValues2()在EC2服务器上没有返回承诺;尝试记录返回的值/对象以查看它是什么。