首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在NodeJS (蓝知更鸟)中通过承诺链持久化数据

如何在NodeJS (蓝知更鸟)中通过承诺链持久化数据
EN

Stack Overflow用户
提问于 2016-05-27 16:31:31
回答 1查看 881关注 0票数 0

跟进Swap order of arguments to "then" with Bluebird / NodeJS Promises (张贴的答案有效,但立即透露了一个新的问题)

这是我第一次在NodeJS中使用承诺,所以如果某些约定没有得到遵守或者代码草率,我很抱歉。我试图聚合来自多个API的数据,将其放在数据库中,然后根据数据的异同计算一些统计数据。作为一个起点,我试图为其中一个API获取一个API令牌。

这是我的完整代码:

代码语言:javascript
复制
var Promise = require('bluebird');
var fs = require('fs');
var request = require('request');
Promise.promisifyAll(fs);
Promise.promisifyAll(request);

// tilde-expansion doesn't follow the callback(err, data) convention
var tilde = function(str) {
    var _tilde = require('tilde-expansion');
    return new Promise(function(resolve, reject) {
        try {
            _tilde(str, resolve);
        } catch(e) {
            reject(e);
        }
    });
}

var getToken = function() {
    return request.getAsync(process.env.token_url, {
        headers: {
            "Content-Type": "applications/x-www-form-urlencoded"
        },
        form: {
            client_id: process.env.client_id,
            client_secret: process.env.client_secret,
            grant_type: "client_credentials"
        }
    })
        .then(function(resp) { return resp.body; });
}

var tokenFile = tilde(process.env.token_file)
    .catch(function(err) {
        console.log("Error parsing path to file... can not recover");
    });

var token = tokenFile
    .then(fs.readFileAsync) //, "utf8")
    .then(function(data) {
        console.log("Token (from file): " + data);
        return data;
    })
    .then(JSON.parse)
    .catch(function(err) {
        console.log("Error reading token from file... getting a new one");
        return getToken()
            .then(function(data) {
                console.log("Token (from API): " + data);
                return data;
            })
            .then(JSON.stringify)
            .then(fs.writeFileAsync.bind(null, tokenFile.value()));
    });

token.then(function(data) {
    console.log("Token (from anywhere): " + token.value);
});

此代码目前正在日志记录:

代码语言:javascript
复制
Token: undefined

如果我回到API。假设我正确地做了我的承诺(.catch()可以回报一个承诺,对吗?)然后,我假设这个问题正在发生,因为fs.writeFileAsync返回了void。

我想在这个承诺的末尾附加一个.return(),但是如何访问getToken()的返回值呢?我尝试了以下几点:

代码语言:javascript
复制
    .catch(function(err) {
        console.log("Error reading token from file... getting a new one");
        var token = "nope";
        return getToken()
            .then(function(data) {
                console.log("Token (from API): " + data);
                token = data;
                return data;
            })
            .then(JSON.stringify)
            .then(fs.writeFileAsync.bind(null, tokenFile.value()))
            .return(token);
    });

然而,这是“不”。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-31 14:15:27

在周末,我继续我的承诺研究,并在一个关键的认识到,我能够找到解决这个问题的办法。在这里发布实现和解决方案:

实现

承诺的发明使得异步代码可以以同步的方式使用。请考虑以下几点:

代码语言:javascript
复制
var data = processData(JSON.parse(readFile(getFileName())));

这相当于:

代码语言:javascript
复制
var filename = getFileName();
var fileData = readFile(filename);
var parsedData = JSON.parse(fileData);
var data = processData(parsedData);

如果这些函数中的任何一个是异步的,那么它就会中断,因为值没有按时准备好。因此,对于那些我们曾经使用回调的异步位:

代码语言:javascript
复制
var filename = getFileName();
var data = null;
readFile(filename, function(fileData){
    data = processData(JSON.parse(fileData));
});

这不仅是丑陋的,而且打破了很多东西,如堆栈跟踪,尝试/捕捉块,等等。

承诺模式修复了这个问题,您可以这样说:

代码语言:javascript
复制
var filename = getFileName();
var fileData = filename.then(readFile);
var parsedData = fileData.then(JSON.parse);
var data = parsedData.then(processData);

不管这些函数是同步的还是异步的,并且没有回调,这段代码都能工作。它实际上都是同步代码,但我们不是传递值,而是传递承诺。

这使我认识到:对于每一段可以用承诺编写的代码,都有一个同步的推论。

解决方案

意识到这一点,如果所有函数都是同步的,我尝试考虑我的代码:

代码语言:javascript
复制
try {
    var tokenFile = tilde(process.env.token_file)
} catch(err) {
    throw new Error("Error parsing path to file... can not recover");
}

var token = null;
try {
    token = JSON.parse(readFile(tokenFile));
} catch(err) {
    token = getToken();
    writeFile(tokenFile, JSON.stringify(token));
}

console.log("Token: " + token.value);

在像这样构建它之后,承诺版本在逻辑上如下:

代码语言:javascript
复制
var tokenFile = tilde(process.env.token_file)
    .catch(function(err) {
        throw new Error("Error parsing path to file... can not recover");
    });

var token = tokenFile
    .then(readFile)
    .then(JSON.parse)
    .catch(function(err) {
        var _token = getToken();
        _token
            .then(JSON.stringify)
            .then(writeFile.bind(null, tokenFile.value));
        return _token;
    });
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37488385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档