62009030
62009030

Reputation: 347

Promise Angularjs 1.6 How can I force function to wait for api response

Im using this plugin: http://www.codingdrama.com/bootstrap-markdown/

I want to hook the onPreview

So on onPreview i try to make my api call:

   app.directive("markdowntextarea",function ($http, $q) { // inject $q
    return {
        link: function (el_scope, element, attr) {
            element.markdown(
                {
                    autofocus: false,
                    savable: false,
                    onPreview: function (e) {
                        var deferred = $q.defer();
                        if (e.isDirty()) {
                            var originalContent = e.getContent();
                            $http({
                                url: '/api/markdown/',
                                data: {"body": originalContent, "actual_format": "md"},
                                method: 'POST'
                            }).then(function successCallback(response) {
                                console.log("successCallback", response.data.content);
                                deferred.resolve(response.data.content);
                            }, function errorCallback(response) {
                                console.log("errorCallback");
                                deferred.reject("error");
                            });
                        } else {
                            deferred.resolve("");
                        }
                        return deferred.promise;
                    }
                }
            );
        }
    }
});

Console:

successCallback from api!!!

I got success response from api, the response.data.content is what I want to use. The problem here is the return deferred.promise; always return the original value. What can I do here? I'm really new in angularjs

Upvotes: 0

Views: 1400

Answers (2)

user2009750
user2009750

Reputation: 3187

With promises you can't return values at once, usually you return promise object called promise handle and using 'then' clause you wait for promise to resolve(successfully) or reject(failure).

In your case if you want to wait for response and then do something I suggest you call onPreview and use its then clause like:

onPreview(e).then(function(response){}, function(error){});

onPreview is already returning promise which should be thenable.

After Edit:

So onPreview is API method and is expecting a text not promise, now what you can do is define a function like makePreview or something:

function makePreview(e) {
    var deferred = $q.defer();
    if (e.isDirty()) {
        var originalContent = e.getContent();
        $http({
            url: '/api/markdown/',
            data: {"body": originalContent, "actual_format": "md"},
            method: 'POST'
        }).then(function successCallback(response) {
            console.log("successCallback", response.data.content);
            deferred.resolve(response.config.data.body);
        }, function errorCallback(response) {
            console.log("errorCallback");
            deferred.reject("error");
        });
    } else {
        deferred.resolve("");
    }
    return deferred.promise;
}

and then your onPreview should look like this:

autofocus: false,
savable: false,
onPreview: function (e) {
    makePreview(e).then(function(response){
        e.setContent(response);
        return response;
    }, function(error){
        return error;
    });
}

I hope this helps :)

Upvotes: 1

Valens
Valens

Reputation: 164

You cannot write angular in absolute sync way. Use the response in callback. If you need to control api requests' order, or wait for multiple requests, see doc of $q

Upvotes: 0

Related Questions