使用 await 后无法获得 Promise 的结果

我的函数长这样:

async function getPlaceForecast(lat, long) {
//var response;
var day5forecast = 'http://api.openweathermap.org/data/2.5/forecast?lat=' + lat + '&lon=' + long + '&appid=' + apikey;
try {
    const request = new Request(tmp2, {
        method: 'get'
    })
    let response = await fetch(request)
        .then(value => {
            console.log("than", value.json());
            return value//.json();
        })
        .catch(function (error) {
            console.error(error);
        });
}
catch{

}
//return response;

这是结果:

'than', { _40: 0, _65: 0, _55: null, _72: null }

而不使用 .json() 的结果是:

'than', { type: 'default',
status: 200,
ok: true,
   statusText: undefined,
  headers:
   { map:
     { 'access-control-allow-methods': 'GET, POST',
       'access-control-allow-credentials': 'true',
        'access-control-allow-origin': '*',
        'x-cache-key': '/data/2.5/forecast?lat=28.35&lon=-14.05',
        connection: 'keep-alive',
       'content-length': '14383',
      'content-type': 'application/json; charset=utf-8',
         server: 'openresty' } },
  url: 'http://api.openweathermap.org/data/2.5/forecast?lat=28.349414&lon=-14.046311&appid=<mykey>',
  _bodyInit:
    { _data:
     { size: 14383,
       offset: 0,
   blobId: '2dbf82c5-5d28-47db-9034-7f239bf8290a' } },
  _bodyBlob:
   { _data:
      { size: 14383,
       offset: 0,
        blobId: '2dbf82c5-5d28-47db-9034-7f239bf8290a' } } }

我哪里做错了?

点赞
用户157247
用户157247

你正在记录 json() 返回的 promise,而不是 promise 的完成值。

以下是函数的写法:

async function getPlaceForecast(lat, long) {
    const day5forecast = 'http://api.openweathermap.org/data/2.5/forecast?lat=' + lat + '&lon=' + long + '&appid=' + apikey;

    const request = new Request(day5forecast, {
        method: 'get'
    })
    let response = await fetch(request);
    if (!response.ok) {
        throw new Error("HTTP error " + response.status);
    }
    return response.json();
}

注意我已经删除了 try/catch。它交给调用方去处理,这样他们就知道 getPlaceForecast 是否成功或失败。

你可能会想到最后一行缺少 await (return response.json();)。但实际上不需要,因为 async函数总是返回一个 promise。return response.json(); 将异步函数的 promise 解析为 json() 返回的 promise,所以它将根据 json() promise 的结果完成或拒绝。你可以在那里使用 await (return await response.json();) 也没有影响,¹ 但实际上不需要。


¹ 具体来说:A)在现代浏览器中,它是完全无害的,这是由于 ES2019 的改变;在那之前,由于 promise 不是原生promise,理论上整体完成/拒绝会延迟一个额外的异步 “tick”(如果返回的 promise 不是原生promise,这仍然会发生);B)即使有额外的 tick,这是大部分无害的。 :-)

2020-05-14 07:18:10