Nodejs 承诺所有内容都不会按预期运行



我有一系列的承诺,我已经testCard .此方法获取stripe卡号,从 stripe 获取令牌,然后与尝试使用该卡执行购买的第三方 API 通信。我需要通过循环浏览一系列卡号来运行testCard。为此,我有一个带有方法testAllCardscontroller对象,该方法采用数字数组。数组存储在配置文件中。

然后,我使用 node cli.js testAllCards 从命令行运行代码。

但是,当我运行它时,在所有大多数承诺解决之前,我都会testAllCards has been run。我在这里显然错过了一些东西,但似乎无法弄清楚它是什么。

命令行.js

const testAllCards = () => {
  return controller.testAllCards(config.get('CARD_NUMBERS'))
    .then((obj) => {
      console.log('testAllCards has been run');
    })
    .catch((e) => {
      console.log('testCards has been run with an error!');
      const _err = new ErrHandler(e, eTopicName, eSnsSubject);
      _err.handle()
        .then(() => {
          console.log('Error has been sent with success to sns');
        });
    });
};
switch(process.argv[2]) {
  case 'testAllCards':
    testAllCards();
    break;
  default:
    console.log('Please run with `testAllCards`');

控制器.js

//Tests response from API for different cards
const testCard = (cardNum) => {
  return new Promise((resolve, reject) => {
    const expMonth = new Date().getMonth() + 1;
    const expYear = new Date().getFullYear() + 2;
    const cardObj = {
      cardNum: cardNum,
      expMonth: expMonth,
      expYear: expYear
    };
    let apiCardItem = '';
    return testRequestToApi('getStripeToken', 200, 299, cardObj)
      .then((cardItem) => {
        return testRequestToApi('postNewCard', 200, 299, JSON.parse(cardItem.body));
      })
      .then((apiCard) => {
        apiCardItem = apiCard.body;
        try {
          apiCardItem = JSON.parse(apiCardItem);
        } catch(e) {
          console.log(e);
        }
        return testRequestToApi('sampleAddToCart', 200, 299);
      })
      .then(() => {
        return testRequestToApi('useFailingStripeCards', 400, 499, apiCardItem.id);
      })
      .then(() => {
        return testRequestToApi('deleteCard', 200, 299, apiCardItem.id);
      })
      .then(() => {
        resolve();
      })
      .catch((e) => {
        reject(e);
      });
  });
};
//Loops through the card numbers and runs the test command against them
Controller.testAllCards = (cardsArray) => {
  const items = cardsArray.map((cardNum) => {
    return testCard(cardNum);
  });
  return Promise.all(items);
};
module.exports = Controller;

测试请求到 API.js

'use strict';
const checkStatus = require('./../utils/status-code-checker');
const formHeaders = require('./../utils/form-req-headers');
const request     = require('request');
const expObj = {};
//@requestType {string} - defines which headers and function name to use
//@item {object} - defines item that is being used
expObj.testRequestToApi = (requestType, lowerLimit, upperLimit, item) => {
  return new Promise((resolve, reject) => {
    const reqOps = formHeaders[requestType](item);
    request(reqOps, (err, response, body) => {
      if (err) {
        const badRequest = {
          ErrorMessage: err,
          FuncName: requestType,
          InternalError: true
        };
        return reject(badRequest);
      }
      if (!checkStatus.checkRangeStatusCode(response.statusCode, lowerLimit, upperLimit)) {
        console.log(JSON.stringify(body, null, 2));
        // Set a bad Status error object
        let badStatus = {
          StatusCode: response.statusCode,
          ErrorMessage: body,
          FuncName: requestType,
          InternalError: false
        };
        return reject(badStatus);
      }
      // console.log(response.headers);
      // console.log(body);
      const resObj = {
        headers: response.headers,
        body: body
      };
      // console.log(`******** ${requestType} *********`);
      // console.log(resObj);
      // console.log('----------------------------------');
      return resolve(resObj);
    });
  });
};
module.exports = expObj;
了解仅在

承诺基于回调的 API 时才需要使用new Promise(),更改为 request-promise 并在 cli.js 中返回我的承诺解决了我的问题。以这种方式正确维护了执行流。

对以下文件的更改如下所示:命令行.js

const testAllCards = () => {
  return controller.testAllCards(config.get('CARD_NUMBERS'))
    .then((obj) => {
      console.log('testAllCards has been run');
    })
    .catch((e) => {
    console.log(e)
      console.log('testCards has been run with an error!');
      const _err = new ErrHandler(e, eTopicName, eSnsSubject);
      return _err.handle()
        .then(() => {
          console.log('Error has been sent with success to sns');
        })
        .catch((e) => {
          console.log('Failed to publish to sns');
          console.log(e);
        });
    });
};

测试请求到接口

'use strict';
const checkStatus = require('./../utils/status-code-checker');
const formHeaders = require('./../utils/form-req-headers');
const rqp         = require('request-promise');
const expObj = {};
//@requestType {string} - defines which headers and function name to use
//@item {object} - defines item that is being used
expObj.testRequestToApi = (requestType, lowerLimit, upperLimit, item) => {
  const reqOps = formHeaders[requestType](item);
  return rqp(reqOps)
    .then((response) => {
      if (!checkStatus.checkRangeStatusCode(response.statusCode, lowerLimit, upperLimit)) {
        console.log(JSON.stringify(response.body, null, 2));
        // Set a bad Status error object
        return {
          StatusCode: response.statusCode,
          ErrorMessage: response.body,
          FuncName: requestType,
          InternalError: false
        };
      }
      // console.log(response.headers);
      // console.log(response.body);
      const resObj = {
        headers: response.headers,
        body: response.body,
        previousItem: item
      };
      // console.log(`******** ${requestType} *********`);
      // console.log(resObj);
      // console.log('----------------------------------');
      return resObj;
    })
    .catch((e) => {
      return {
        ErrorMessage: e,
        FuncName: requestType,
        InternalError: true
      };
    });
};
module.exports = expObj;

控制器.js

//Tests response from API for different cards
Controller.testCard = (cardNum) => {
  const expMonth = new Date().getMonth() + 1;
  const expYear = new Date().getFullYear() + 2;
  const cardObj = {
    cardNum: cardNum,
    expMonth: expMonth,
    expYear: expYear
  };
  let apiCardItem = '';
  return testRequestToApi('getStripeToken', 200, 299, cardObj)
    .then((cardItem) => {
      return testRequestToApi('postNewCard', 200, 299, JSON.parse(cardItem.body));
    })
    .then((apiCard) => {
      apiCardItem = apiCard.body;
      try {
        apiCardItem = JSON.parse(apiCardItem);
      } catch(e) {
        console.log('Already a JSON object -----> Moving on');
      }
      return testRequestToApi('sampleAddToCart', 200, 299);
    })
    .then(() => testRequestToApi('useFailingStripeCards', 400, 499, apiCardItem.id))
    .then(() => testRequestToApi('deleteCard', 200, 299, apiCardItem.id));
};
//Loops through the card numbers and runs the test command against them
Controller.testAllCards = (cardsArray) => {
  return Promise.all(cardsArray.map((cardNum) => {
    return Controller.testCard(cardNum);
  }));
};
module.exports = Controller;

我重写了你的"testCard"函数(控制器.js(

//Tests response from API for different cards
const testCard = (cardNum) => {
  return new Promise((resolve, reject) => {
    let apiCardItem = '';
    const expDate = new Date();
    const cardObj = {
      cardNum:  cardNum,
      expMonth: expDate.getMonth() + 1,
      expYear:  expDate.getFullYear() + 2
    };
    
    testRequestToApi('getStripeToken', 200, 299, cardObj)
      .then((cardItem) => testRequestToApi('postNewCard', 200, 299, JSON.parse(cardItem.body)))
      .then((apiCard) => {
        apiCardItem = apiCard.body;
        try {
          apiCardItem = JSON.parse(apiCardItem);
        } catch(e) {
          console.log(e);
        }
        return testRequestToApi('sampleAddToCart', 200, 299);
      })
      .then(() => testRequestToApi('useFailingStripeCards', 400, 499, apiCardItem.id))
      .then(() => testRequestToApi('deleteCard', 200, 299, apiCardItem.id))
      .then(resolve)
      .catch(reject);
  });
};

还有你的"testRequestToApi"(test-request-to-api.js(

expObj.testRequestToApi = (requestType, lowerLimit, upperLimit, item) => {
  return new Promise((resolve, reject) => {
    const reqOps = formHeaders[requestType](item);
    request(reqOps, (err, response, body) => {
      let badStatus  = {};
      let badRequest = {};
      let resObj     = {};
      if (err) {
        badRequest = {
          ErrorMessage:  err,
          FuncName:      requestType,
          InternalError: true
        };
        reject(badRequest);
        return false;
      }
      
      if (!checkStatus.checkRangeStatusCode(response.statusCode, lowerLimit, upperLimit)) {
        console.log(JSON.stringify(body, null, 2));
        // Set a bad Status error object
        badStatus = {
          StatusCode:    response.statusCode,
          ErrorMessage:  body,
          FuncName:      requestType,
          InternalError: false
        };
        reject(badStatus);
        return false;
      }
      resObj = {
        headers: response.headers,
        body:    body
      };
      resolve(resObj);
    });
  });
};

我认为问题是当你在决定/拒绝被调用之前从承诺中返回时。

还要检查在嵌套承诺中,为了简洁起见,您可以将解析/拒绝传递给 .then/catch。

最新更新