确保程序在设置之前从数据库中检索凭据

Ensuring the program retrieves the credentials from the database BEFORE setting them

我对 Javascript 和 promises 比较陌生,所以我不确定如何确保代码在这种情况下遵循特定顺序。

基本上,我需要在设置凭据之前从数据库中检索凭据。如何确保检索代码发生在设置代码之前 - 有没有办法使用 async 和 await 来执行此操作?

首先需要完成的代码以**admin.firestore().collection('credentials').get().then(async (snapshot) => {**

开头

需要排在第二位的代码是

**client_id: Credentials.client_id,
        client_secret: Credentials.client_secret**

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: `https://${process.env.GCLOUD_PROJECT}.firebaseio.com`
});


admin.firestore().collection('credentials').get().then(async (snapshot) => {
    await snapshot.docs.forEach(doc => {
        console.log(JSON.stringify(doc.data().client_id));
        // Credentials.client_id = JSON.stringify(doc.data().client_id);
        console.log(JSON.stringify(doc.data().client_secret));
        // Credentials.client_secret = JSON.stringify(doc.data().client_secret);
        let client_id = JSON.stringify(doc.data().client_id);
        let client_secret = JSON.stringify(doc.data().client_secret);


        const regex = /(\w)+/g;

        let m;
        let n;
        while ((m = regex.exec(client_id)) !== null) {
            // This is necessary to avoid infinite loops with zero-width matches
            if (m.index === regex.lastIndex) {
                regex.lastIndex++;
            }

            // The result can be accessed through the `m`-variable.
            m.forEach((match, groupIndex) => {
                Credentials.client_id = match;
                console.log(`Found match, group ${groupIndex}: ${match}`);

            });
        }
        while ((n = regex.exec(client_secret)) !== null) {
            // This is necessary to avoid infinite loops with zero-width matches
            if (n.index === regex.lastIndex) {
                regex.lastIndex++;
            }

            // The result can be accessed through the `n`-variable.
            n.forEach((match, groupIndex) => {
                Credentials.client_secret = match;
                console.log(`Found match, group ${groupIndex}: ${match}`);

            });
        }
    });


});

class Credentials {

    constructor(client_id, client_secret) {
        this.client_id = client_id;
        console.log('Id in class ' + this.client_id);
        this.client_secret = client_secret;
        console.log('Secret in class ' + this.client_secret);

    }

}

/**
 * ----------------------Below section of code found at: LINK TO GIT REPOSTITORY---------------------------------
 */
// Spotify OAuth 2 setup
const SpotifyWebApi = require('spotify-web-api-node');
const Spotify = new SpotifyWebApi({
    
    client_id: Credentials.client_id,
    client_secret: Credentials.client_secret,
    redirectUri: `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com/popup.html`
});

我在程序运行时收到 [object Promise] 或 undefined。但是在控制台日志上,几秒钟后它记录了我需要的数据。真的坚持这个 - 任何人都知道如何解决这个问题? (下面的代码是导致 [object Promise] 情况的当前状态。

client_id: Promise.resolve(admin.firestore().collection('credentials').get().then(async (snapshot) => {
        await snapshot.docs.forEach(doc => {
            JSON.stringify(doc.data().client_id);})})),
    client_secret: (admin.firestore().collection('credentials').get().then(async (snapshot) => {
        await snapshot.docs.forEach(doc => {
            JSON.stringify(doc.data().client_secret);})})),

您已经使用此行首先检索凭据

admin.firestore().collection('credentials').get()

此函数 return 是一个 Promise,您可以继续使用 then,就像您已经拥有的那样,或者使用 async/await 从函数中检索值.

承诺 & Async/Await

将其用作 Promisethen

await admin.firestore().collection('credentials').get().then((snapshot => {
    // Credentials have been retrieved.
    // Continue here to use the credentials.
});

或者在 async/await 函数中使用它。

async function getCredentials() {
    const snapshot = await admin.firestore().collection('credentials').get();
    return snapshot;
}

两者都会 return 一个 Promise 但选择权在您。

现在您的代码中有几处必须更改,位置错误或使用方式不当。

凭据

您创建了一个名为 Credentialsclass。虽然 class 定义是正确的,但实例化不是。要创建 class 的新实例,请使用 new 关键字。 class 实际上是一个对象的蓝图,可以在代码中的任何位置使用 new 关键字创建。

const client_id = 'yourclientid';
const client_secret = 'yourclientsecret';
const credentials = new Credentials(client_id, client_secret);

// {
//     client_id: 'yourclientid',
//     client_secret: 'yourclientsecret'
// }

展示位置

因为admin.firestore().collection('credentials').get()是一个异步函数,它不会停止文件的处理。文件的其余部分将在不等待凭据检索的情况下执行。但是您想在 检索凭据后对其进行处理。您可以使用 Promisethen 方法来做到这一点。只要 Promiseresolved,就会调用 then。表示已经等待完毕,可以继续了。

因此,只要检索到凭据,Spotify 部分就必须在 内部 then 方法中。

admin.firestore().collection('credentials').get().then((snapshot) => {
    // We are in the then method, so credentials have been retrieved.

    snapshot.docs.forEach(doc => {
       // Check the credentials...
       // ...

       // Create your credentials object. 
       const credentials = new Credentials(client_id, client_secret);

       // Create new Spotify session.
       const Spotify = new SpotifyWebApi({
           client_id: credentials.client_id,
           client_secret: credentials.client_secret,
           redirectUri: `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com/popup.html`
       });

    });
});

需要

这并不重要,但将 require 语句放在页面顶部是一个很好的做法。这让您或任何其他阅读代码的人清楚地知道此文件中包含哪些文件或依赖项。

// Put me at the top of the page.
const SpotifyWebApi = require('spotify-web-api-node');

结论

这就是我通过查看您的代码所能知道的全部内容。您走在正确的轨道上,但仍需要阅读更多有关 Promises 工作原理的信息,更重要的是 whywhen do you use他们。

then 方法回调中创建 Spotify 会话,并使用 new 关键字创建 Credentials class.