【问题标题】:Why is it not waiting for an awaited Promise.all to resolve?为什么不等待等待的 Promise.all 解决?
【发布时间】:2021-08-02 07:28:05
【问题描述】:

我之前的工作代码在可迭代的每个元素上调用等待效率低下。我正在重构以使用 Promise.All。 但是,我的代码没有等待 Promise.All 在执行进一步代码之前解决。

具体来说,purgeRequestPromises 行在初始 Promise.All 解析之前执行。我不确定这是为什么? retrieveSurrogateKey 是一个异步函数,因此它的返回行将被包裹在一个已解析的 Promise 中。

try {
    //retrieve surrogate key associated with each URL/file updated in push to S3
    const surrogateKeyPromises = urlArray.map(url => this.retrieveSurrogateKey(url));
    const surrogateKeyArray = await Promise.all(surrogateKeyPromises).catch(console.log);

    //purge each surrogate key
     const purgeRequestPromises = surrogateKeyArray.map(surrogateKey => this.requestPurgeOfSurrogateKey(surrogateKey));
     await Promise.all(purgeRequestPromises);

     // GET request the URLs to warm cache for our users
     const warmCachePromises = urlArray.map(url => this.warmCache(url));
     await Promise.all(warmCachePromises)
} catch (error) {
    logger.save(`${'(prod)'.padEnd(15)}error in purge cache: ${error}`);
    throw error
} 

async retrieveSurrogateKey(url) {
    try {
        axios({
            method: 'HEAD',
            url: url,
            headers: headers,
        }).then(response => {
            console.log("this is the response status: ", response.status)
            if (response.status === 200) {
                console.log("this is the surrogate key!! ", response.headers['surrogate-key'])
                return response.headers['surrogate-key'];
            }

        });
    } catch (error) {
        logger.save(`${'(prod)'.padEnd(15)}error in retrieveSurrogateKey: ${error}`);
        throw error
    }
}

我知道 purgeRequestPromises 会提前执行,因为我收到错误消息,抱怨我在 HEAD 请求中将 Surrogate-Key 标头设置为 undefined

async requestPurgeOfSurrogateKey(surrogateKey) {
    headers['Surrogate-Key'] = surrogateKey

    try {
        axios({
                method: `POST`,
                url: `https://api.fastly.com/service/${fastlyServiceId}/purge/${surrogateKey}`,
                path: `/service/${fastlyServiceId}/purge${surrogateKey}`,
                headers: headers,
            })
            .then(response => {
                console.log("the status code for purging!! ", response.status)
                if (response.status === 200) {
                    return true
                }
            });
    } catch (error) {
        logger.save(`${'(prod)'.padEnd(15)}error in requestPurgeOfSurrogateKey: ${error}`);
        throw error;
    }
}

【问题讨论】:

  • 如果你能提供一个Minimal, Reproducible Example 那就太好了,这样我们就可以调试发生了什么。
  • retrieveSurrogateKey() 没有返回 axios 调用
  • 解释示例代码:jsfiddle.net/khrismuc/dhcmr5fe
  • "retrieveSurrogateKey 是一个异步函数,因此它的返回行将包含在已解决的承诺中。" - 但您的代码中没有任何内容表明该承诺应该等待 @ 987654330@ 调用,并注意 retrieveSurrogateKey 函数确实没有return 语句。

标签: javascript async-await promise axios


【解决方案1】:

retrieveSurrogateKey 正在同步返回undefinedtry 块中的值是一个promise,不会同步抛出任何错误,所以catch 子句永远不会执行,执行掉到底部,返回@987654325 @来自函数体。

你可以试试这样的:

function retrieveSurrogateKey(url) {  // returns a promise
    return axios({
//  ^^^^^^
        method: 'HEAD',
        url: url,
        headers: headers,
    }).then(response => {
        console.log("this is the response status: ", response.status)
        if (response.status === 200) {
            console.log("this is the surrogate key!! ", response.headers['surrogate-key'])
            return response.headers['surrogate-key'];
        }

    }).catch(error => {
       logger.save(`${'(prod)'.padEnd(15)}error in retrieveSurrogateKey: ${error}`);
       throw error;
    });
}

请注意,如果函数不使用await,则将返回承诺的函数声明为async 是多余的。这一行还有一个次要问题:

const surrogateKeyArray = await Promise.all(surrogateKeyPromises).catch(console.log);

catch 子句将履行承诺链,除非错误被重新抛出。您可以(也许)放弃.catch 子句或将其重新编码为

.catch( err=> { console.log(err); throw err} );

【讨论】:

  • "try 块中的值是一个promise,不会同步抛出任何错误,所以catch 子句永远不会被执行,执行落到底部,从函数调用返回undefined。" 它返回Promise.resolve(undefined),而不是undefined。此外,您可以保留原样并在调用axios(...) 之前插入return await,而不是删除async 并使所有内容成为promise 链,以便将promise 拒绝传播到catch 块在原始代码中。
  • @PatrickRoberts 将 call 更改为 body 以确保准确性。承诺链已经出现在问题中,因此我将 catch 块转换为 catch 子句以保持一致性。
【解决方案2】:

您无需从 retrieveSurrogateKey() 中删除 async 即可使其正常工作。事实上,如果你不这样做,它更具可读性。正如已经解释过的,问题在于retrieveSurrogateKey() 返回的promise 不遵循对axios() 的调用返回的promise 的完成。你需要await它:

async retrieveSurrogateKey(url) {
  try {
    const response = await axios({
      method: 'HEAD',
      url,
      headers,
    });

    console.log('this is the response status: ', response.status);

    if (response.status === 200) {
      const surrogateKey = response.headers['surrogate-key'];
      console.log('this is the surrogate key!! ', surrogateKey);
      return surrogateKey;
    }
  } catch (error) {
    logger.save(`${'(prod)'.padEnd(15)}error in retrieveSurrogateKey: ${error}`);
    throw error;
  }
}

这保留了您当前拥有的相同逻辑,但您会注意到,当 response.status !== 200 时,您最终会得到 undefined 的已解决承诺,而不是被拒绝的承诺。您可能希望使用validateStatus 来断言 200 的确切状态。默认情况下,axios 解析任何状态 >= 200 和

async retrieveSurrogateKey(url) {
  try {
    const response = await axios({
      method: 'HEAD',
      url,
      headers,
      validateStatus(status) {
        return status === 200;
      } 
    });
    
    const surrogateKey = response.headers['surrogate-key'];
    console.log('this is the surrogate key!! ', surrogateKey);
    return surrogateKey;
  } catch (error) {
    logger.save(`${'(prod)'.padEnd(15)}error in retrieveSurrogateKey: ${error}`);
    throw error;
  }
}

这样,您始终可以保证使用代理键或被拒绝的承诺。

【讨论】:

    猜你喜欢
    • 2020-06-23
    • 2019-04-29
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多