Bluebird promise变量:'undefined不是函数;

Bluebird promise variable: 'undefined is not a function'

本文关键字:undefined 函数 promise 变量 Bluebird      更新时间:2023-09-26

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

使用AWS RDS MySQL数据库在localhost上一切都很好,但当我将服务器上传到我的AWS EC2实例时,我发现这个函数有问题:

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声明为新的Promise,因为根据if条件,它将接收不同数据库查询函数的值(这些函数返回Promise)。

当我调用这个函数时,结果是:"未定义的不是函数"

我理解这种行为的发生是因为它执行的第一个findValue.then()而不是if/else块代码,并且由于变量未定义,它可以是一个函数。

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

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

谢谢你的建议!!

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

在JavaScript中,不将变量声明为任何类型。此行:

var findValue = new Promise();

声明一个变量(var findValue)并尝试创建一个promise(= new Promise())。Promise构造函数要求为其传递函数。它试图将其第一个参数用作函数,由于您没有向它传递任何参数,因此它将为第一个参数获取undefined—从而产生误差。

可以将其更改为

var findValue;

但是您的代码正成为不必要的promise创建谬论的牺牲品:只需使用您已经拥有的promise:

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;
}

假设您的db.getValues1/db.getValues2函数返回promise(它们似乎没有回调,我拒绝假设您在生产中使用同步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。不要那样做。Promisify标准、符合节点的函数/库,使用Bluebird的Promisify例程。

  2. 蓝鸟2.x和3.x将在var findValue = new Promise()上投球。正如已经指出的,构造函数需要一个函数作为其参数。我怀疑你转述了你实际收到的错误信息。如果是这样的话,不要这样做,这会让其他人很难弄清楚哪里出了问题。

  3. 下次你发布到SO时,请将你的示例代码减少到任何人都可以运行的代码,并随时修复你的问题。你可能会发现,在进行最小的指责的过程中,你解决了自己的问题。如果你不这样做,这将使这里的人们能够更有效地帮助你。

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

以下是重现问题的一句话:

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

输出:

未处理的拒绝类型错误:未定义不是函数

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

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

至于为什么会发生这种情况,那一定是Sequelize的一个错误。如果您仍然遇到问题,请提交。

您的.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服务器上没有返回promise;尝试记录返回的值/对象以查看它是什么。