Search code examples
javascriptjqueryajaxpromisees6-promise

Returning a Javascript Promise from $.ajax call


I am attempting to cast a $.ajax() statement to an es6 Promise and return the es6 promise. The idea is that I will have an application layer of Create, Update, Delete calls to the Microsoft Dynamics Web API which return an es6 Promise so that I can reuse the Create, Update, Delete calls across multiple pages. I've read through the Google, MDN, and David Walsh Blog articles about es6 Promises as well as several SO questions, but I haven't been able to quite put together the details yet.

In my code below, when ExpenseUpload.js calls expenseTransactionSetAPI.Create(newExpenseTransactionSet).then(...)); I see the execution getting to the then(), but nothing inside the then() is being executed. I'm not quite sure what changes I need to make so that my code execution actually processes the then() and I'm not even sure if I am using es6 Promises correctly. Any guidance would be appreciated.

ExpenseUpload.js

"use strict";

requirejs.config({
    bundles: {
        'CCSEQ.WebAPI.js': ['Model/ExpenseTransaction', 'Model/ExpenseTransactionSet', 'API/ExpenseTransaction', 'API/ExpenseTransactionSet']
    }
});

require(["Model/ExpenseTransaction", "Model/ExpenseTransactionSet", "API/ExpenseTransaction", "API/ExpenseTransactionSet"], function (ExpenseTransactionModel, ExpenseTransactionSetModel, ExpenseTransactionAPI, ExpenseTransactionSetAPI) {

let file;

$(document).ready(() => {
    setupHandlers();
});

function setupHandlers() {
    $("#csv-file").change((e) => {
        file =  e.target.files[0];
    });

    $("#btnUploadFile").click(() => loadFile());
}

function loadFile() {
    Papa.parse(file, {
        complete: (results) => {
            ImportExpenseTransaction(results.data);
            console.log("import complete");
        }
    });
}

function ImportExpenseTransaction(data) {
    let newExpenseTransactionSet = new ExpenseTransactionSetModel.ExpenseTransactionSet();
    newExpenseTransactionSet.SetName = $("#UploadName").val();
    newExpenseTransactionSet.Month = $("#UploadMonth").val();
    newExpenseTransactionSet.Year = $("#UploadYear").val();
    newExpenseTransactionSet.ImportDate = new Date();
    newExpenseTransactionSet.Status = 100000000;        

    let newExpenseTransactions = new Array();
    data.forEach((expense) => {
        if (expense[0] !== "PR EMP ID") {
            let newRecord = new ExpenseTransactionModel.ExpenseTransaction();
            newRecord. = expense[n];  
            ... // Load other records like above
            newExpenseTransactions.push(newRecord);
        }
    });

    let expenseTransactionSetAPI = new ExpenseTransactionSetAPI.ExpenseTransactionSet();
    let expenseTransactionAPI = new ExpenseTransactionAPI.ExpenseTransaction();
    expenseTransactionSetAPI.Create(newExpenseTransactionSet).
        then((data) => {
            console.log(data);
            console.log("Transaction Set Created");
            expenseTransactionAPI.
                Create(newExpenseTransactions[0]).
                then(() => {
                    console.log("Transaction Created");
                }).catch(() => {
                    console.log("failure");
                });
        }).catch(() => {
            (data) => {
                console.log(data);
                console.log("failure");
            }
        });        
}
});

CCSEQ.WebAPI.js

define("API/ExpenseTransaction", ["require", "exports", "API/APIBase", "Model/ExpenseTransaction"], function (require, exports, APIBase_1, Model) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    class ExpenseTransaction extends APIBase_1.APIBase {
        constructor() {
            super();
            this.ConvertToEntity = (data) => {
                let result = new Array();
                for (let i = 0; i < data.length; i++) {
                    let newRecord = new Model.ExpenseTransaction();
                    newRecord.[field] = data[i]["fieldName"];
                    .
                    .
                    .
                    result[i] = newRecord;
                }
                return result;
            };
        }
        Create(expense) {
            return new Promise((resolve, reject) => {
                $.ajax({
                    url: this.ExpenseTransaction,
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    data: JSON.stringify(expense.toJSON()),
                    success: (data) => { resolve(data); },
                    error: (data) => { reject(data); }
                });
            });
        }
        ;
    }
    exports.ExpenseTransaction = ExpenseTransaction;
});
define("API/ExpenseTransactionSet", ["require", "exports", "API/APIBase", "Model/ExpenseTransactionSet"], function (require, exports, APIBase_2, Model) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    class ExpenseTransactionSet extends APIBase_2.APIBase {
        constructor() {
            super();
            this.ConvertToEntity = (data) => {
                let result = new Array();
                for (let i = 0; i < data.length; i++) {
                    let newRecord = new Model.ExpenseTransactionSet();
                    newRecord.[field] = data[i]["fieldName"];
                    .
                    .
                    .
                    result[i] = newRecord;
                }
                return result;
            };
        }
        Create(expenseSet) {
            return new Promise((resolve, reject) => {
                $.ajax({
                    url: this.ExpenseTransactionSet,
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    data: JSON.stringify(expenseSet.toJSON()),
                    success: (data) => {
                        resolve(data);
                    },
                    error: (data) => {
                        reject(data);
                    }
                });
            });
        }
        ;
    }
    exports.ExpenseTransactionSet = ExpenseTransactionSet;
});
//# sourceMappingURL=CCSEQ.WebAPI.js.map

Solution

  • Just return the ajax requests, it returns a promise-like Object.

    The jqXHR objects returned by $.ajax() as of jQuery 1.5 implement the Promise interface, giving them all the properties, methods, and behavior of a Promise

    Create(expense) {
           return $.ajax({
                url: this.ExpenseTransactionSet,
                type: "POST",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                data: JSON.stringify(expenseSet.toJSON())
            });
    }