【问题标题】:How to work with promise chains if the subsequent promises will be returned based on the condition?如果后续的承诺将根据条件返回,如何使用承诺链?
【发布时间】:2020-10-13 19:36:09
【问题描述】:

我们有一个需要运行 API-1 的要求。如果成功并且 API 响应的结果为“真”,我需要运行 API-2,如果成功并且 API 响应的结果为“真”,我需要运行 API-3。我尝试如下使用承诺链。

runMethodGeneric('A').then((data, status, xhr) => {
    if(xhr.status === 200) {
        if(data.result === 'true') {
            runGenieMethodGeneric('B');
        } else {
            console.log('A result is false');
        }
    }
}).then((data, status, xhr) => {
    console.log(data);
    if(xhr.status == 200) {
        if(data.result === 'true') {
            runGenieMethodGeneric('C');
        } else {
            console.log('B result is false');
        }
    }
}).then((data, status, xhr) => {
    console.log(data);
    if(xhr.status === 200) {
        if(data.result === 'true') {
            console.log('C result is true');
        } else {
            console.log('C result is false');
        }
    }
}).catch((jqXhr, textStatus, errorMessage) => {
    console.log(errorMessage);      
});

runMethodGeneric 是运行所有 API 的通用方法,定义如下。

function runMethodGeneric(method) {
    let url = 'http://192.168.1.253:55678/cl';

    const json = {
        user_data: data,
        params: [],
        gene_method: method,
        requestedAction: 'RUN_GENIE_METHOD'
    };

    let jsonStr = JSON.stringify(json);

    return $.ajax(url, {
        type: 'POST',
        dataType: 'JSON',
        data: jsonStr,
    });
}

我在 jquery 的 html 中使用“https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js”。

第一个 API 调用“A”正在运行,并且控制正在点击第一个“then”块,然后执行第二个 API 调用“B”。当控制点击第二个“then”块时,数据、状态和 xhr 都未定义,即使第二个 API 调用“B”正在工作并获得正确的结果。

jQuery.Deferred exception: Cannot read property 'status' of undefined TypeError: Cannot read property 'status' of undefined
    at http://localhost:5000/chat.js:95:10
    at j (https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js:2:29999)
    at k (https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js:2:30313) undefined

谁能帮我解决以下问题。

  1. 我想知道这是否是做承诺链的正确方法?因为 runMethodGeneric 函数返回 promise。但不确定如何使用 API 调用 B 和 C 返回的那些承诺,因为我正在根据结果调用这些 API 调用。
  2. 如果上述方法不正确,如何做满足要求的promise链(运行API-1。如果成功并且API响应的结果为'true',则运行API-2,如果成功并且结果的 API 响应为“真”,运行 API-3)
  3. 我需要在“then”块中检查 xhr.status === 200 吗?我认为只有当 API 调用成功时,控制才会到达“then”块。这个假设正确吗?

【问题讨论】:

    标签: javascript promise es6-promise


    【解决方案1】:

    您可以使用async/await 语法和for...of 循环来简化此操作,这将允许您一个接一个地执行请求,您还可以将条件添加到循环之外的break

    function fetchData(method) {
      let url = `https://jsonplaceholder.typicode.com/todos/${method}`;
      return $.ajax(url, {
        type: 'GET'
      });
    }
    
    async function runMethods() {
      const methods = [1, 2, 'foo', 3, 4];
    
      for (let method of methods) {
        try {
          const response = await fetchData(method);
    
          // do your checking here
          // break out of the loop if condition true
          if (response.id == 3) {
            console.log(response)
            console.log('exiting on 3')
            break;
          } else {
            console.log(response)
          }
        } catch (err) {
          // you can also break on error here
          console.log(`${err.status} for ${method} method`)
        }
      }
    }
    
    runMethods()
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    【讨论】:

    • 我没有处理异步/等待。我会经历那个。几个问题。如果在 API 调用期间发生任何错误,则响应包含来自等待的内容。它是否包含错误对象?如果是,我如何知道 API 调用是成功还是失败?如果没有,我如何获得错误响应。
    • 好问题,我忘了添加try...catch,现在我已经更新了我的答案。在 catch 块中,如果抛出错误,您可以访问错误(在演示中,当方法为 'foo` 时,它将抛出 404),您可以在那里决定是否要跳出循环或执行其他操作。默认情况下会继续执行下一个请求。
    • @kadina 我认为任何不以 2 开头的响应都会发送给 catch,但我不确定。也许您想重新考虑一些其他替代方法来发出请求,例如 axios 或 js 内部 fetch api,看起来像这样 jsfiddle.net/znmr7btL
    • id 是指 A、B、C 吗?
    • 我知道了 Nenad。无论如何,我在 for 循环的“方法”中有 id。所以我应该知道与哪个 API 相关的响应。谢谢。
    【解决方案2】:

    基本上,您的函数 runMethodGeneric 返回一个 Promise

    function runMethodGeneric(method) {
        let url = 'http://192.168.1.253:55678/cl';
    
        const json = {
            user_data: data,
            params: [],
            gene_method: method,
            requestedAction: 'RUN_GENIE_METHOD'
        };
    
        let jsonStr = JSON.stringify(json);
    
         // HERE IS YOUR RETURN FUNCTION
        return $.ajax(url, {
            type: 'POST',
            dataType: 'JSON',
            data: jsonStr,
        });
    }
    

    所以,当你执行这个函数时,你需要有.then() 来解析来自这个函数的响应

    我想你可以在这里找到答案https://stackoverflow.com/a/16045729/11397634

    【讨论】:

    • 非常感谢。该函数正在返回承诺。但问题是只有当第一个 API 调用将数据中的结果字段返回为 true 时,我才应该运行第二个 API 调用。所以我不能使用first.then(second)。
    猜你喜欢
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多