node.js承诺不强制执行函数的顺序

时间:2016-04-30 17:41:13

标签: javascript node.js promise

我有三个函数,我想使用promises强制它们按顺序执行。

函数1发送http请求,获取JSON数据并将其保存到文件中 函数2循环遍历该文件,并根据缺少的差值/值更新数据库 函数3将遍历新更新的数据库并创建第二个json文件。

目前,函数1完全独立,setInterval为30分钟。

我想在功能1完成时启动功能2。功能2完成后功能3。

使用promises我试图将函数2附加到一个简单的完成日志,以了解如何使用promises但没有取得多大成功。 for循环日志中的项目,但是我的for循环之前的Finished / err日志应该不会发生。有什么建议吗?

function readJson() {
    return new Promise(function() {
        fs.readFile(__dirname + "/" + "bitSkin.json", 'utf8', function read(err, data) {
            if (err) { throw err; }
            var bitCon = JSON.parse(data);  

            for(var i=0; i<7; i++) { //bitCon.prices.length; i++) {
                var price = bitCon.prices[i].price
                var itemName = bitCon.prices[i].market_hash_name;
                (function() {
                    var iNameCopy = itemName;
                    var priceCopy = price;
                    logger.info(iNameCopy);
                }());
            }
        });
    });
};

function fin() {
    logger.info("Finished");
}

readJson().then(fin(), console.log("err"));

1 个答案:

答案 0 :(得分:4)

承诺没有神奇的力量。他们不会神奇地知道他们内部的异步代码何时完成。如果您创建了一个承诺,当异步代码出错或完成时,您自己必须resolve()reject()

然后,此外,您必须将函数引用传递给.then()处理程序,而不是执行函数的结果。 .then(fin())会立即致电fin()并将其返回值传递给.then(),这不是您想要的。你想要.then(fin)

之类的东西

以下是解决和拒绝您创建的承诺的方法:

function readJson() {
    return new Promise(function(resolve, reject) {
        fs.readFile(__dirname + "/" + "bitSkin.json", 'utf8', function read(err, data) {
            if (err) { return reject(err); }
            var bitCon = JSON.parse(data);  

            for(var i=0; i<7; i++) { //bitCon.prices.length; i++) {
                var price = bitCon.prices[i].price
                var itemName = bitCon.prices[i].market_hash_name;
                (function() {
                    var iNameCopy = itemName;
                    var priceCopy = price;
                    logger.info(iNameCopy);
                }());
            }
            resolve(bitCon);
        });
    });
};

而且,你可以这样使用:

function fin() {
    logger.info("Finished");
}
readJson().then(fin, function(err) {
    console.log("err", err)
});

变更摘要:

  1. 添加了解决方案,拒绝Promise回调的参数,以便我们可以使用它们
  2. 出现错误时调用reject(err)
  3. 异步代码完成后调用resolve()
  4. 为两个.then()处理程序传递了一个函数引用。
  5. 仅供参考,在围绕异步函数创建promise包装器时,通常最好只包装函数本身。这使得包装器100%可重用,并将更多代码放在promise架构中,这通常简化了事情并使错误处理更容易。你可以像这样解决问题:

    fs.readFilePromise = function(file, options) {
        return new Promise(function(resolve, reject) {
            fs.readFile(file, options, function(err, data) {
                if (err) return reject(err);
                resolve(data);
            });
        });
    });
    
    function readJson() {
        return fs.readFilePromise(__dirname + "/" + "bitSkin.json", 'utf8').then(function(data) {
            var bitCon = JSON.parse(data);
            bitCon.prices.forEach(function(item) {
                logger.info(item.market_hash_name);
            });
            return bitCon;
        });
    }