Cocos2d networking promise

hello everyone, I’m new with cocos2dx and c++
I try to send a request and return value using a promise.
here is my code:

int getSomeThing(){
    std::promise<int> p;
    std::future<int> f = p.get_future();
    cocos2d::network::HttpRequest* request = new cocos2d::network::HttpRequest();
    request->setUrl("https://www.google.com");
    request->setRequestType(cocos2d::network::HttpRequest::Type::GET);
    request->setResponseCallback([&](cocos2d::network::HttpClient* sender, cocos2d::network::HttpResponse* response) {
        p.set_value(9);
        });
    cocos2d::network::HttpClient::getInstance()->send(request);
    request->release();

    auto result = f.get();
    return result;
}

The responseCallback never called so it stuck at f.get()
i also working with firestore and use the same method to fetch data from firestore and it work perfectly. It must be something weird with cocos thread and I don’t know how to handle it. Can any one help me!!!

I have never actually used std::promise but there is an example in cpp-tests that doesn’t use std::promise, IIRC.

f.get() is blocking the main thread, and since the cocos main loop is no longer running, the request either doesn’t get sent out, or if it does get sent out, it doesn’t get processed, since the callback needs to happen on the cocos main thread as well.

Test it out without the promise/future asynchronous code, and if it works, then you’ll know what the problem is.

Thank to @R101 . I have solved my problem.
My solution is move responseCallback out of cocos thread. So it can perform when cocos thread blocked. It will effect all other request so be careful with it.
here is my solution:

  • I create additional bool value for HttpRequest.h:
    and create getter, setter for it:
    std::vector<std::string>    _headers;        /// custom http headers
    std::string                 _pFilePath;
    std::vector<std::pair<std::string, std::string>> _postFileParams; //vector params. LAST ELEMENT 

    bool                        _isPerformCallbackInCocosThread;
  • In the HttpClient.cpp
    find
if (nullptr != _scheduler)
        {
            _scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
        }

replace it with:

if (nullptr != _scheduler)
        {
            if (request->getIsPerformCallbackInCocosThread()) {
                _scheduler->performFunctionInCocosThread(CC_CALLBACK_0(HttpClient::dispatchResponseCallbacks, this));
            }
            else {
                dispatchResponseCallbacks();
            }
        }
  • Finally:
int getSomething() {
    std::promise<int> p;
    std::future<int> f = p.get_future();
    cocos2d::network::HttpRequest* request = new cocos2d::network::HttpRequest();
    request->setUrl("https://www.google.com/");
    request->setRequestType(cocos2d::network::HttpRequest::Type::GET);
    request->setPerformCallbackInCocosThread(false);
    request->setResponseCallback([&](cocos2d::network::HttpClient* sender, cocos2d::network::HttpResponse* response) {
        p.set_value(9);
        });
    cocos2d::network::HttpClient::getInstance()->send(request);
    request->release();

    auto result = f.get();
    return result;
}
  • I recommend that you set default value for _isPerformCallbackInCocosThread at HttpRequest constructor:
    HttpRequest()
        : _requestType(Type::UNKNOWN)
        , _pTarget(nullptr)
        , _pSelector(nullptr)
        , _pCallback(nullptr)
        , _pUserData(nullptr)
        , _isPerformCallbackInCocosThread(true)
    {
    }

that’s work for me. Feel free to commnent if you anything wrong with these code. Thank you all!!