如果后续承诺将根据条件返回,如何使用承诺链?

How to work with promise chains if the subsequent promises will be returned based on the condition?

我们有一个要求,我需要 运行 API-1。如果成功并且API响应的结果是'true',我需要运行API-2,如果成功并且API响应的结果是'true',我需要运行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);      
});

运行MethodGeneric 是 运行 所有 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,
    });
}

我在 html 中使用 'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js' 用于 jquery。

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

基本上,你的函数 runMethodGeneric return 一个 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() 来解析来自此函数的响应

我想你可以在这里找到答案

您可以使用 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>