Featured image of post 异步Promise的取值问题

异步Promise的取值问题

该如何取出Promise对象中的值?

推荐阅读:

阮一峰 ECMAScript 6 入门

阮一峰 FetchAPI 教程

当初学者想要通过 fetch 等异步方法获取后台返回值的时候,常常会遇到有关Promise的取值问题,现有一异步方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
async function getData() {
  fetch(URL, mySettings)
    .then(response => {
      console.log(response.json());
      return response.json();
    })
    .catch(response => {
      console.log("error:" + response.ok);
    });
}

运行后控制台返回:

1
2
Promise {<pending>}
error: undefined

显然不是我们想要的结果。

针对第一条,我们 console 出了一个处于pending状态的Promise对象,这说明在第一个.then还没结束时,Promise会一直被标记为pending,直到.then方法结束,Promise才会被标记为fulfilled或者rejected。而对于Promise对象而言,其中的值我们并不能直接调用,正如我们不能从当前调用未来的值。

针对第二条,需要明确的是,response 包含的数据是通过 Stream 接口异步读取的, 部分针对response使用的方法如.json().text()等都会把response对象标为已读。就像在一个单向流通的管道里只运送一个物物品,那么在任何时候任何地点把东西取出,在此之后就无法从管道中取出物品,因为它已经被取出了,因此,在此之后所有对response对象进行的调用都会出问题,因为你已经读取过response的值了,所以才会打印出error

现在我们可以理解,在调用fetch方法时首先会返回一个Promise对象,那么我们应该如何取出其中的值呢?首先需要使用.json()方法将Promise解析为JSON格式,并且再次使用.then进行链式调用才能取出其中的值。

将代码进行改进

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
async function getData() {
  fetch(URL, mySettings)
    .then(response => {
      return response.json();
      //直接return出respo.json()
    })
    .catch(response => {
      console.log("error:" + response.ok);
    })
    .then(data => {
      console.log(data.result);
      //第一个.then传出response.json()作为第二个.then的参数data输入
    });
}

此时我们就可以在控制台得到正确的数据了,

当然,现在我们通常会使用封装好的 http 请求库进行接口调用和数据交互,如AxiosRequestSuperagent

1
2
3
4
5
6
7
8
9
import axios from "axios";
axios
  .get(url)
  .then(response => {
    this.list = response.data.result;
  })
  .catch(e => {
    console.log("error when fetching Data!");
  });

使用这些库就可以减少取值的步骤,简化请求的流程和代码,提高我们的开发效率。

Built with Hugo
主题 StackJimmy 设计