.then () выполняется до того, как будут выполнены вложенные обещание. все и выборки - PullRequest
4 голосов
/ 11 мая 2019

Я пытаюсь создать приложение, которое получает данные из API, используя fetch в Javascript. Вот структура JSON для пары URL

myapi.com / list возвращает: [{id: 111, пользователь: nam1}, {id: 222, пользователь: nam2}] Затем я должен сделать еще один запрос с одним из этих идентификаторов пример: myapi.com/list/111 возвращает:

[{id:111,user:name1,description: "some text",public:true}]

пример: myapi.com/list/111/posts возвращает:

[{a1:"some data",a2:"some data2"},{b1:"some data",b2:"some data2"},{c1:"some data",c2:"some data2"}]

по нескольким причинам мне нужно создать функцию, которая возвращает 1 массив, группирующий их все в следующем формате:

   [
    {id:111,user:name1,description: "some text",public:true, 
    posts:[{a1:"some data",a2:"some data2"},{b1:"some data",b2:"some data2"},{c1:"some data",c2:"some data2"}]
    },
    {id:222,user:name2,description: "some text2",public:true
    posts:[{a1:"some data",a2:"some data2"},{b1:"some data",b2:"some data2"},{c1:"some data",c2:"some data2"}
    }
    ]

Вот моя основная программа Это прекрасно работает из-за setTimeOut:

    Promise.all([FetchFunctionThatworks(),FetchfunctionWithPrblm() ])
    .then(values => new State(values[0], values[1]))
    .then(state => {console.log(state) ; 

      setTimeout(function(){
      functionA(state); // a function that prints some html with the result of the FetchfunctionWithPrblm

  },200)
   ;} )
    .catch(reason => console.error(reason));

Я хочу удалить setTimeout, но проблема в том, что мой код внутри .then () вызывает функцию A до того, как обещание разрешено, поэтому в структуре, которую я получаю, не хватает "posts", с помощью setTimeOut я получаю желаемый результат.

Вот моя функция FetchWithPrblm ()

function FetchfunctionWithPrblm() {
  const url = serverUrl+ "list/";
   return fetch(url).then(
    id_list => id_list.json()
  ).then(
    list_data => Promise.all(
      list_data.map(topic => fetch(url +topic.id)
      .then(response =>  response.json()  )
      )
    ) /**end 1st promise.all */

  ) .then(ListNopost =>{
    ListNopost.map( single_entry =>{
      Promise.all( [fetch( url + single_entry.id+ '/posts').then(resp=>resp.json() ) ] )
      .then (posts_data =>{
        single_entry.posts=posts_data[0];
      })
    })
    return ListNopost;
  })
}

Разве обещание не вернется, только когда обещание будет выполнено? Может кто-нибудь сказать мне, что я делаю не так? И помочь мне исправить это?

Заранее спасибо

1 Ответ

3 голосов
/ 11 мая 2019

Ваша проблема здесь:

ListNopost.map( single_entry =>{
   Promise.all( [fetch( url + single_entry.id+ '/posts').then(resp=>resp.json() ) ] )
   .then (posts_data =>{
     single_entry.posts=posts_data[0];
   })
})
return ListNopost;

Promise.all никогда не возвращается, поэтому ваше основное обещание разрешается раньше, чем fetch s.Также обратите внимание, что map не является мутатором и должен возвращать значение, если вы хотите, чтобы оно было включено в новый массив.

Попробуйте это:

var promises = ListNopost.map(single_entry => {
    return fetch(url + single_entry.id + '/posts')
        .then(resp => resp.json())
        .then(posts_data => {
            single_entry.posts = posts_data[0]
            return single_entry
        })
})
return Promise.all(promises)
...