Метод жизненного цикла Gatsby createPages, выполняемый до того, как метод onCreateNode завершит добавление необходимых полей узла - PullRequest
0 голосов
/ 06 августа 2020

Я работаю над сайтом Gatsby, который использует gatsby-source-wordpress. В моем файле gatbsy- node.js я использую метод жизненного цикла onCreateNote, чтобы определить, является ли узел определенным настраиваемым типом сообщения WordPress, затем я обращаюсь к отдельному API, чтобы получить связанную информацию для типа сообщения, используйте createNodeField, чтобы добавить его в качестве поля, а иногда также использовать createRemoteFileNode для добавления изображений, полученных из API, в поле на новом узле.

Теперь это отлично работает большую часть времени, но иногда метод жизненного цикла createPages выполняется, пока изображение / код узла все еще происходит (я считаю). Это означает, что поля изображения еще не существуют, и создание страницы не выполняется. Затем, после сбоя, я вижу консольное сообщение в журнале, который я настроил, где оно уведомляет меня об успешном добавлении нового поля к узлу.

Как я могу убедиться, что все эти узлы завершено и данные завершены, ДО запуска жизненного цикла createPages? Кажется, что когда клиент загружает изображение большего размера, это с большей вероятностью потерпит неудачу ... что имеет смысл, если я правильно это понимаю. Вот код из моего файла gatsby- node.js:

const path = require(`path`);
const slash = require(`slash`);

const fetch = require('node-fetch');
const { createRemoteFileNode } = require(`gatsby-source-filesystem`)


exports.onCreateNode = ({ node, actions, store, cache,createNodeId, }) => {
    const { createNode, createNodeField } = actions;

    function getData(url) {
        return new Promise((resolve, reject) => {
            fetch(url)
                .then((response) => response.json())
                .then((data) => {
                    resolve(data);
                });
        })
    }

    if( node.internal.type === "wordpress__wp_location"){
        const yextID = node.acf.yext_entity_id;
        const yextOrthos = node.acf.location_orthodontists;

        try {

            const getLocation = async () => {
                const data = await fetch("https://api.yext.com/v2/accounts/me/entities?api_key=" + process.env.YEXT_API_KEY + "&v=20191114&filter=%7B%22%24anywhere%22%3A%20%22" + yextID + "%22%7D&entityTypes=healthcareFacility")
                .then(response => response.json());

                // Transform the data into json
                if( data && data.response && data.response.count === 1 ){
                    createNodeField({
                        node,
                        name: `yextLocation`,
                        value: data.response.entities[0]
                    });
                } else {
                    console.log("NO LOCATIONS FOUND");
                }
            };

            function getOrthos(){
                let orthodontists = [];

                yextOrthos.forEach( (ortho, i) => {
                    orthodontists.push(getData("https://api.yext.com/v2/accounts/me/entities?api_key=" + process.env.YEXT_API_KEY + "&v=20191114&filter=%7B%22%24anywhere%22%3A%20%22" + ortho.acf.yext_entity_ortho_id + "%22%7D&entityTypes=healthcareProfessional"));
                });

                Promise.all(orthodontists).then( (orthoData) => {
                    if( orthoData.length ){
                        let finalOrthos = [];

                        orthoData.forEach( (finalOrtho, x) => {
                            finalOrthos.push(finalOrtho.response.entities[0]);
                        });

                        createNodeField({
                            node,
                            name: `yextOrthos`,
                            value: finalOrthos
                        });

                    } else {
                        console.log("NO DOCTORS FOUND");
                    }
                });
            }

            getLocation();
            getOrthos();

        } catch (error) {
            console.log(error);
        }
    }

    if( node.internal.type === "wordpress__wp_orthodontist"){
        const yextID = node.acf.yext_entity_ortho_id;
        const wpID = node.wordpress_id;

        try {

            const getTextOrtho = async () => {
                const data = await fetch("https://api.yext.com/v2/accounts/me/entities?api_key=" + process.env.YEXT_API_KEY + "&v=20191114&filter=%7B%22%24anywhere%22%3A%20%22" + yextID + "%22%7D&entityTypes=healthcareProfessional")
                .then(response => response.json());

                // Transform the data into json
                if( data && data.response && data.response.count === 1 ){
                    googleProfilePhoto = data.response.entities[0].googleProfilePhoto.url;
                    createNodeField({
                        node,
                        name: `yextOrthodontist`,
                        value: data.response.entities[0]
                    });

                    if( data.response.entities[0].googleProfilePhoto && data.response.entities[0].googleProfilePhoto.url){
                        createNodeField({
                            node,
                            name: `yextProfilePicture`,
                            value: data.response.entities[0].googleProfilePhoto.url
                        });

                        let fileNode = await createRemoteFileNode({
                            url: data.response.entities[0].googleProfilePhoto.url, // string that points to the URL of the image
                            parentNodeId: node.id, // id of the parent node of the fileNode you are going to create
                            createNode, // helper function in gatsby-node to generate the node
                            createNodeId, // helper function in gatsby-node to generate the node id
                            cache, // Gatsby's cache
                            store, // Gatsby's redux store
                        })
                        // if the file was created, attach the new node to the parent node
                        if (fileNode) {
                            console.log("GOOGLE PROFILE NODE CREATED!")
                            node.featuredImg___NODE = fileNode.id
                        } else {
                            console.log("ERROR! fileNode not Created!");
                        }
                    } else {
                        console.log("NO GOOGLE PROFILE PHOTO FOUND");
                    }
                    
                } else {
                    console.log("NO ORTHODONTISTS FOUND");
                }
            }

            const getWpLocations = async () => {
                const data = await fetch(process.env.GATSBY_WP_BASEURL+ "/wp-json/custom_endpoint/v1/locations_by_orthodontist?orthodontist_id=" + wpID).then(response => response.json());

                if( data ){
                    createNodeField({
                        node,
                        name: `wpLocations`,
                        value: data
                    });
                } else {
                    console.log("NO ORTHODONTISTS FOUND");
                }
            }

            getTextOrtho();
            getWpLocations();

        } catch (error) {
            console.log(error);
        }
    }

}

exports.createPages = async ({ graphql, actions }) => {
    const { createPage } = actions;

    const result = await graphql(`
        {
            locations: allWordpressWpLocation(filter: {status: {eq: "publish"}}) {
                nodes {
                    id
                    path
                    acf {
                        location_orthodontists {
                            acf {
                                yext_entity_ortho_id
                            }
                        }
                        yext_entity_id
                    }
                }
            }
            pages: allWordpressPage(
                filter: {
                    wordpress_id: {nin: [177, 183, 8, 42, 44, 185, 46]}
                    status: {eq: "publish"}
                }) {
                nodes {
                    id
                    wordpress_id
                    path
                }
            }
            orthodontists: allWordpressWpOrthodontist(filter: {status: {eq: "publish"}}) {
                nodes {
                    id
                    path
                }
            }
            posts: allWordpressPost(filter: {status: {eq: "publish"}}) {
                nodes {
                    slug
                    id
                }
            }
        }
    `);

    // Check for any errors
    if (result.errors) {
        throw new Error(result.errors);
    }

    const { locations, pages, orthodontists, posts } = result.data;

    const locationTemplate = path.resolve(`./src/templates/location.js`);
    const pageTemplate = path.resolve(`./src/templates/page.js`);
    const orthoTemplate = path.resolve(`./src/templates/orthodontist.js`);
    const postTemplate = path.resolve(`./src/templates/post.js`);
    const blogTemplate = path.resolve(`./src/templates/blog.js`);

    locations.nodes.forEach(node => {
        let orthodontists = [];

        node.acf.location_orthodontists.forEach(ortho => {
            orthodontists.push(ortho.acf.yext_entity_ortho_id);
        });

        let orthodontistList = orthodontists.join();

        createPage({
            path: `${node.path}`,
            component: slash(locationTemplate),
            context: {
                id: node.id,
                yextId: node.acf.yext_entity_id,
                yextOrthoIds: orthodontists
            },
        });
    });

    pages.nodes.forEach(node => {
        createPage({
            path: `${node.path}`,
            component: slash(pageTemplate),
            context: {
                id: node.id,
            },
        });
    });

    orthodontists.nodes.forEach(node => {
        createPage({
            path: `${node.path}`,
            component: slash(orthoTemplate),
            context: {
                id: node.id,
            },
        });
    });

    posts.nodes.forEach(node => {
        createPage({
            path: `${node.slug}`,
            component: slash(postTemplate),
            context: {
                id: node.id,
            },
        });
    });

    const postsPerPage = 12;
    const numPages = Math.ceil(posts.nodes.length / postsPerPage);
    Array.from({ length: numPages }).forEach((_, i) => {
        createPage({
            path: i === 0 ? `/blog` : `/blog/page/${i + 1}`,
            component: slash(blogTemplate),
            context: {
                limit: postsPerPage,
                skip: i * postsPerPage,
                numPages,
                currentPage: i + 1,
            },
        })
    })
};

Спасибо за любую информацию, которую вы можете предоставить! Я предполагаю, что это, вероятно, связано с тем, что я все еще учусь использовать асинхронное поведение в JS, но я просто не могу найти информацию о том, как это сделать.

Пожалуйста, дайте мне знать, могу ли я объяснить ситуация лучше!

1 Ответ

1 голос
/ 06 августа 2020

После перезаписи это, похоже, решило мою проблему. Честно говоря, я все еще работаю над полным пониманием тонкостей функций async / await / promises в JS, но, надеюсь, если кто-то столкнется с аналогичной проблемой, просмотр этой перезаписи может помочь:

const path = require(`path`);
const slash = require(`slash`);

const fetch = require('node-fetch');
const { createRemoteFileNode } = require(`gatsby-source-filesystem`)


exports.onCreateNode = async ({ node, actions, store, cache,createNodeId, }) => {
    const { createNode, createNodeField } = actions;

    const getData = async (url) => {
        return new Promise((resolve, reject) => {
            fetch(url)
                .then((response) => response.json())
                .then((data) => {
                    resolve(data);
                });
        })
    }

    const getLocation = async (yextID) => {
        const data = await getData("https://api.yext.com/v2/accounts/me/entities?api_key=" + process.env.YEXT_API_KEY + "&v=20191114&filter=%7B%22%24anywhere%22%3A%20%22" + yextID + "%22%7D&entityTypes=healthcareFacility");

        // Transform the data into json
        if( data && data.response && data.response.count === 1 ){
            createNodeField({
                node,
                name: `yextLocation`,
                value: data.response.entities[0]
            });
        } else {
            console.log("NO LOCATIONS FOUND");
        }
    };

    const getOrthos = async (yextOrthos) => {
        let orthodontists = [];

        yextOrthos.forEach( (ortho, i) => {
            orthodontists.push(getData("https://api.yext.com/v2/accounts/me/entities?api_key=" + process.env.YEXT_API_KEY + "&v=20191114&filter=%7B%22%24anywhere%22%3A%20%22" + ortho.acf.yext_entity_ortho_id + "%22%7D&entityTypes=healthcareProfessional"));
        });

        Promise.all(orthodontists).then( (orthoData) => {
            if( orthoData.length ){
                let finalOrthos = [];

                orthoData.forEach( (finalOrtho, x) => {
                    finalOrthos.push(finalOrtho.response.entities[0]);
                });

                createNodeField({
                    node,
                    name: `yextOrthos`,
                    value: finalOrthos
                });

            } else {
                console.log("NO DOCTORS FOUND");
            }
        });
    };

    const getTextOrtho = async (yextID) => {
        const data = await getData("https://api.yext.com/v2/accounts/me/entities?api_key=" + process.env.YEXT_API_KEY + "&v=20191114&filter=%7B%22%24anywhere%22%3A%20%22" + yextID + "%22%7D&entityTypes=healthcareProfessional");

        if( data && data.response && data.response.count === 1 ){
            createNodeField({
                node,
                name: `yextOrthodontist`,
                value: data.response.entities[0]
            });

            if( data.response.entities[0].googleProfilePhoto && data.response.entities[0].googleProfilePhoto.url){
                createNodeField({
                    node,
                    name: `yextProfilePicture`,
                    value: data.response.entities[0].googleProfilePhoto.url
                });

                let fileNode = await createRemoteFileNode({
                    url: data.response.entities[0].googleProfilePhoto.url, // string that points to the URL of the image
                    parentNodeId: node.id, // id of the parent node of the fileNode you are going to create
                    createNode, // helper function in gatsby-node to generate the node
                    createNodeId, // helper function in gatsby-node to generate the node id
                    cache, // Gatsby's cache
                    store, // Gatsby's redux store
                });
                // if the file was created, attach the new node to the parent node
                if (fileNode) {
                    node.featuredImg___NODE = fileNode.id;
                    console.log("GOOGLE PROFILE NODE CREATED!")
                } else {
                    console.log("ERROR! fileNode not Created!");
                }
            } else {
                console.log("NO GOOGLE PROFILE PHOTO FOUND");
            }
            
        } else {
            console.log("NO ORTHODONTISTS FOUND");
        }
    };

    const getWpLocations = async (wpID) => {
        const data = await getData(process.env.GATSBY_WP_BASEURL+ "/wp-json/perch_endpoint/v1/locations_by_orthodontist?orthodontist_id=" + wpID);

        if( data ){
            createNodeField({
                node,
                name: `wpLocations`,
                value: data
            });
        } else {
            console.log("NO ORTHODONTISTS FOUND");
        }
    }

    if( node.internal.type === "wordpress__wp_location"){
        const yextID = node.acf.yext_entity_id;
        const yextOrthos = node.acf.location_orthodontists;

        try {
            await getLocation(yextID);
            await getOrthos(yextOrthos);
        } catch (error) {
            console.log(error);
        }

    }

    if( node.internal.type === "wordpress__wp_orthodontist"){
        const yextID = node.acf.yext_entity_ortho_id;
        const wpID = node.wordpress_id;

        try {
            await getTextOrtho(yextID);
            await getWpLocations(wpID);
        } catch (error) {
            console.log(error);
        }
    }

}

exports.createPages = async ({ graphql, actions }) => {
    const { createPage } = actions;

    const result = await graphql(`
        {
            locations: allWordpressWpLocation(filter: {status: {eq: "publish"}}) {
                nodes {
                    id
                    path
                    acf {
                        location_orthodontists {
                            acf {
                                yext_entity_ortho_id
                            }
                        }
                        yext_entity_id
                    }
                }
            }
            pages: allWordpressPage(
                filter: {
                    wordpress_id: {nin: [177, 183, 8, 42, 44, 185, 46]}
                    status: {eq: "publish"}
                }) {
                nodes {
                    id
                    wordpress_id
                    path
                }
            }
            orthodontists: allWordpressWpOrthodontist(filter: {status: {eq: "publish"}}) {
                nodes {
                    id
                    path
                }
            }
            posts: allWordpressPost(filter: {status: {eq: "publish"}}) {
                nodes {
                    slug
                    id
                }
            }
        }
    `);

    // Check for any errors
    if (result.errors) {
        throw new Error(result.errors);
    }

    const { locations, pages, orthodontists, posts } = result.data;

    const locationTemplate = path.resolve(`./src/templates/location.js`);
    const pageTemplate = path.resolve(`./src/templates/page.js`);
    const orthoTemplate = path.resolve(`./src/templates/orthodontist.js`);
    const postTemplate = path.resolve(`./src/templates/post.js`);
    const blogTemplate = path.resolve(`./src/templates/blog.js`);

    locations.nodes.forEach(node => {
        let orthodontists = [];

        node.acf.location_orthodontists.forEach(ortho => {
            orthodontists.push(ortho.acf.yext_entity_ortho_id);
        });

        let orthodontistList = orthodontists.join();

        createPage({
            path: `${node.path}`,
            component: slash(locationTemplate),
            context: {
                id: node.id,
                yextId: node.acf.yext_entity_id,
                yextOrthoIds: orthodontists
            },
        });
    });

    pages.nodes.forEach(node => {
        createPage({
            path: `${node.path}`,
            component: slash(pageTemplate),
            context: {
                id: node.id,
            },
        });
    });

    orthodontists.nodes.forEach(node => {
        createPage({
            path: `${node.path}`,
            component: slash(orthoTemplate),
            context: {
                id: node.id,
            },
        });
    });

    posts.nodes.forEach(node => {
        createPage({
            path: `${node.slug}`,
            component: slash(postTemplate),
            context: {
                id: node.id,
            },
        });
    });

    const postsPerPage = 12;
    const numPages = Math.ceil(posts.nodes.length / postsPerPage);
    Array.from({ length: numPages }).forEach((_, i) => {
        createPage({
            path: i === 0 ? `/blog` : `/blog/page/${i + 1}`,
            component: slash(blogTemplate),
            context: {
                limit: postsPerPage,
                skip: i * postsPerPage,
                numPages,
                currentPage: i + 1,
            },
        })
    })
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...