簡體   English   中英

如何通過NodeJS中的Promise鏈持久化數據(Bluebird)

[英]How to persist data through promise chain in NodeJS (Bluebird)

Bluebird / NodeJS Promises的參數交換為“ then”的后續操作(發布的答案有效,但立即發現了一個新問題)

這是我第一次在NodeJS中使用Promise,因此對於某些約定未得到嚴格遵守或代碼草率的行為,我深表歉意。 我正在嘗試聚合來自多個API的數據,將其放入數據庫中,然后根據數據的異同來計算一些統計信息。 首先,我嘗試獲取單個API的API令牌。

這是我的完整代碼:

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

該代碼當前正在記錄:

Token: undefined

如果我退回到API。 假設我正確完成了我的諾言內容( .catch()可以返回一個諾言,對嗎?),那么我會認為問題正在發生,因為fs.writeFileAsync返回void。

我想追加一個.return()這一承諾的結束,但我將如何獲得對返回值的訪問getToken() 我嘗試了以下方法:

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

但是,這記錄為“不”。

在周末,我繼續了對諾言的研究,並且在實現關鍵性實現后,我得以開發出解決方案。 在此同時發布實現和解決方案:

實現

發明了承諾,以便可以以同步方式使用異步代碼。 考慮以下:

var data = processData(JSON.parse(readFile(getFileName())));

這等效於:

var filename = getFileName();
var fileData = readFile(filename);
var parsedData = JSON.parse(fileData);
var data = processData(parsedData);

如果這些函數中的任何一個是異步的,那么它將中斷,因為該值未按時准備好。 因此,對於那些異步位,我們曾經使用回調:

var filename = getFileName();
var data = null;
readFile(filename, function(fileData){
    data = processData(JSON.parse(fileData));
});

這不僅丑陋,而且破壞了很多東西,例如堆棧跟蹤,try / catch塊等。

Promise模式解決了這個問題,讓您說:

var filename = getFileName();
var fileData = filename.then(readFile);
var parsedData = fileData.then(JSON.parse);
var data = parsedData.then(processData);

不管這些函數是同步的還是異步的,此代碼都有效,並且回調為零。 它實際上是所有同步代碼,但是我們傳遞承諾而不是傳遞

使我意識到: 對於可以用promise編寫的每一段代碼,都有一個同步的推論。

解決方案

意識到這一點,我嘗試考慮所有功能是否都是同步的代碼:

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

在像這樣進行構架之后,promise版本在邏輯上如下:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM