Экспортируйте результат из обещания, затем заблокируйте - PullRequest
0 голосов
/ 15 марта 2020

Я довольно новичок в js и мире обещаний, и я прочитал много статей об обещании, обратном вызове, асинхронности / ожидании.

У меня есть функция getAllPost(), которая запрашивает все сообщения из URI.

// get-content.js
export async function getAllPost(){
    let uri     = "http://127.0.0.1/posts";
    let request = axios.get(uri);
    return request;
}
export default getAllPost;

Я пытаюсь использовать результат из getAllPost() для отображения содержимого, и я хочу экспортировать posts.

// posts.js
import * as Navi from 'navi'
import slugify from 'slugify'
import { getAllPost } from './get-content'


let getPost = getAllPost();
let articles;
getPost.then((response) => {
  articles = response;
})

console.log(articles); // undefined.


let postDetails = articles.map( content => {


  let title = content.title;
  let slug = slugify(content.title);
  let date = new Date(content.date);
  let contentKey = content.contentKey;

  return {contentKey, title, slug, date}

})

let posts = postDetails.map(
  ({contentKey, title, slug, date}, i) => 

  ({

    getPage: Navi.map(async () => {

      return Navi.route({
        title,  
        getData: (req, context) => ({
          date,
          slug,
        }),
        getView: async () => {
          let MDXComponent = await getContent(contentKey);
          return { MDXComponent }
        }

      })
    }), 

    slug,

  })


)

export default posts;

Я понимаю, что articles равен undefined, потому что js не будет ждать getPost.then() fini sh.

Я пытался поместить все let postDetails = articles.map(...) и let posts = postDetails.map(...) в getPost.then((response) => { ... }) блок, но в этом случае я не могу экспортировать posts.


getPost.then((response) => {
  let articles = response;
  let postDetails = articles.map( content => {
     ...
  })

  let posts = postDetails.map(
     ...
  )

  export default posts;  // compile failed.
})

Редактировать:

Спасибо за предложения, но я должен быть более ясным.

Вот как я буду использовать сообщения:

import { chunk, fromPairs } from 'lodash'
import posts from './posts'

// posts has to be an array at this point.
let chunks = chunk(posts, n)

Я думаю, мне нужно переписать chunk() разрешить обратный вызов?
https://github.com/lodash/lodash/blob/master/chunk.js

Ответы [ 4 ]

0 голосов
/ 15 марта 2020

Ваша проблема в том, что вы забыли добавить ключевое слово await перед вашим топором ios запрос:

// get-content.js
export default async function(){
   let uri     = "http://127.0.0.1/posts";
   let request = await axios.get(uri);
   return request.data;
}

Не определено, поскольку вы отправляете запрос с axios.get(uri), и этот запрос фактически возвращает результат, но для получения результата требуется некоторое время, скажем, около 100 мс. Например, за 100 мс функция уже завершена и возвращает неопределенное значение. С await вы можете позволить обещаниям, ожидающим вашего запроса, пока вы не получите ответ.

Вторая проблема: поскольку getAllPost() возвращает сам результат, вы можете написать свой код следующим образом:

import getAllPost from "./get-content";
let articles =  getAllPost();
0 голосов
/ 15 марта 2020

Я думаю, вы должны сделать что-то подобное:

export async function fetchArticles() {
    let uri     = "http://127.0.0.1/posts";
    return await axios.get(uri);
}
async function getPosts(){
    const articles = await fetchArticles();
    let postDetails = articles.map(...);
    let posts = postDetails.map(...);

    return posts
}

export default getPosts; // you can't export posts directly, you should export a function and call it to get posts
0 голосов
/ 15 марта 2020

Asyn c -wait - это синтаксис сахара вокруг обещания API. Запись asyn c await не сделает ваш код синхронным.

let getPost = getAllPost();
let articles;
getPost.then((response) => {
  articles = response;
})

console.log(articles); // undefined.

здесь, когда вы вызываете getPost, вы получаете arricles в обратном вызове. Однако console.log (статьи); // не определено. и другая строка будет выполняться раньше, чем даже тогда вызвали Если вы хотите лениво инициализировать что-то, вы должны ждать результата, чем вызывать что-то другое. Ниже я привел пример.

(async function() {
 const articles = await getAllPost()

console.log(articles); // not undefined.

let postDetails = articles.
/// rest of the code
})()

Точно так же, вам нужно решить экспорт сообщений звонить.

0 голосов
/ 15 марта 2020

Ваша функция getAllPosts является экспортом по умолчанию, поэтому вам не нужно заключать ее в фигурные скобки при импорте в следующий скрипт.

Ваш articles не определен, поскольку вы пытаетесь использовать это за пределами функции обещания.

Когда вы вызываете функцию, вы можете сразу же начать выполнять ваши тогда функции, а не передавать ответ другой переменной ...

getAllPost().then(articles => {
  // articles.map etc...
  // The rest of your code must live inside this function
  // because anything outside of here won't wait for the
  // articles promise. 
  // This is async world, outside isn't. 
})

Другая вещь вы можете использовать, если вам не нравится оставаться внутри обещания, функция asyn c await, она намного чище и проще для понимания.

let articles
try {
  articles = await getAllPost()
} catch (err) {
  console.log(err)
}
// Do stuff with articles...

Примечание приведенный выше код должен быть хотя внутри функции asyn c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...