Cannot read property 'then' of undefined in promise

时间:2017-12-18 08:27:34

标签: javascript promise

I have the above error on this method:

function myFunction() {
    var response = UrlFetchApp.fetch("https://www.fastlane.co.il/Mobile.aspx",
                                         {muteHttpExceptions:true});
    Logger.log(response.getContentText());
}

Entire code is here:

function addContentType(listItem){
                var promise = getContentTypeOfCurrentItem(listItem.ID.toString());
                promise.then(function(cname){
                  listItem['Document Type'] = cname; //we add the doc type to each listItem, not only the last one
                });
                return promise;
            }

Not sure exactly what I am missing

Update 1:

I changed the code as Niels replied tere, but then I get the error below:

function GetRelatedBillingDocumentsFromList(selectProperties, currentBillCyclePath, clientCode, jobCodes, engagementCode, enhanceFunctions) {
                $log.info("Retrieving related billing documents for bill cycle with name [" + currentBillCyclePath + "]");                  
                var deferred = $q.defer();
                var webUrl = _spPageContextInfo.webAbsoluteUrl;
                var viewFields = spService.ConvertSelectPropertiesToViewFields(selectProperties);
                // query must return the documents for the same client but in other bill cycles not the current one
                var camlQuery = '<View Scope="RecursiveAll">' +   viewFields + 
                        '<Query>' +
                            '<Where>' +
                                '<And>' +
                                    '<Eq>' +
                                        '<FieldRef Name="ClientCode" />' +
                                        '<Value Type="Text">'+ clientCode + '</Value>' +
                                    '</Eq>' +
                                    '<Neq>' +
                                        '<FieldRef Name="ContentType" />' +
                                        '<Value Type="Computed">Bill Cycle</Value>' +
                                    '</Neq>' +
                                '</And>' +
                            '</Where>' +
                        '</Query>' +
                    '</View>';

                var billCyclesListId = "{c23bbae4-34f7-494c-8f67-acece3ba60da}";                    
                spService.GetListItems(billCyclesListId, camlQuery, selectProperties)
                .then(function(listItems) {                 
                    var listItemsWithValues = [];

                    if(listItems) {
                        var enumerator = listItems.getEnumerator();
                        var promises = [];
                        while (enumerator.moveNext()) {
                            var listItem = enumerator.get_current();
                            var listItemValues = [];                                
                            selectProperties
                            .forEach(function(propertyName) {                               
                                var value = listItem.get_item(propertyName);
                                if(propertyName === "PwC_JobCodesMulti"){
                                    jobvalue = "";
                                    value.forEach(function(jobvalues){
                                        jobvalue+= jobvalues.get_lookupValue() +";";
                                    })
                                    listItemValues[propertyName] = jobvalue;
                                }else{
                                    listItemValues[propertyName] = value;
                                }   
                            });

                            listItemsWithValues.push(listItemValues);
                        }

                        var promises = listItemsWithValues.map(addContentType);
                        Promise.all(promises).then(youCanUseTheData);

                        function youCanUseTheData(){
                            /*
                            At this point, each listItem holds the 'Document Type' info
                            */
                            listItemsWithValues.forEach(function(listItem) {
                                var fileDirRef = listItem["FileRef"];
                                var id = listItem["ID"];
                                var title = listItem["Title"];
                                var serverUrl = _spPageContextInfo.webAbsoluteUrl.replace(_spPageContextInfo.webServerRelativeUrl,"");                          
                                var dispFormUrl = serverUrl + "/sites/billing/_layouts/15/DocSetHome.aspx?id="+fileDirRef;
                                //listItem["FileRef"] = dispFormUrl;
                                //listItem["Bill Cycle"] = dispFormUrl;

                                var parentLink = listItem["FileRef"];
                                arrayofstrings = parentLink.split("/");
                                var billCycleFolderName = arrayofstrings[arrayofstrings.length-2];
                                arrayofstrings.pop();
                                var hyperLink = '<a href="' + arrayofstrings.join('/') + '">' + billCycleFolderName + '</a>';                           
                                listItem["Bill Cycle"] = hyperLink; 

                            });
                        }
                    }                   


                    var enhancedListItemValues = spService.SpSearchQuery.EnhanceSearchResults(listItemsWithValues, enhanceFunctions);                       
                    deferred.resolve(listItemsWithValues);
                })
                .catch (function (message) {
                    deferred.reject();
                });

                return deferred.promise;
            }

            function addContentType(listItem){
                var promise = getContentTypeOfCurrentItem(listItem.ID.toString());
                promise.then(function(cname){
                  listItem['Document Type'] = cname; //we add the doc type to each listItem, not only the last one
                });
                return promise;
            }

            function getContentTypeOfCurrentItem(id) {              
                var clientContext = new SP.ClientContext.get_current();
                var oList = clientContext.get_web().get_lists().getByTitle("Bill Cycles");
                listItem = oList.getItemById(id);
                clientContext.load(listItem);
                listContentTypes = oList.get_contentTypes();
                clientContext.load(listContentTypes);
                clientContext.executeQueryAsync(
                    function() {
                        $log.info("Successfully retrieved getContentTypeOfCurrentItemt");
                        var ctid = listItem.get_item("ContentTypeId").toString();            
                        var ct_enumerator = listContentTypes.getEnumerator();
                        while (ct_enumerator.moveNext()) {
                            var ct = ct_enumerator.get_current();            
                            if (ct.get_id().toString() == ctid) {
                                var contentTypeName = ct.get_name();
                            }
                        }
                        return Promise.resolve(contentTypeName);
                   },
                   function(error, errorInfo) {
                        $log.warn("Retrieving getContentTypeOfCurrentItem failed");
                        deferred.reject(errorInfo);
                   }
                );
            }

If I analyze the changes done, the only thing that changed on the method is the return new promise, the rest is the same and it was working before. I didnt make all changes as Niels did, just need to make this work without too much effort. :)

Uncaught Error: The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.

2 个答案:

答案 0 :(得分:1)

The getContentTypeOfCurrentItem function doesn't return anything. Just modify it to return your promise (assuming of course that // Your application Logic. switch Locale.preferredLanguageMap.first! { case .English : print("Do Something the English Way") case .Spanish : print("Do Something the Spanish Way") default: print("Do Anything... Throw an error/Default Handling.") // Note : Locale.availableIdentifiers has 789 language identifiers till date. // This could also change in the future. // Ensure you have some default logic for all 'other languages' here. } returns a promise):

clientContext.executeQueryAsync

答案 1 :(得分:1)

getContentTypeOfCurrentItem应该返回一个Promise。假设clientContext.executeQueryAsync没有返回promise,因为它正在使用处理程序:

function getContentTypeOfCurrentItem(id) {
    return new Promise(function (resolve, reject) {
        var clientContext = new SP.ClientContext.get_current();
        var oList = clientContext.get_web().get_lists().getByTitle("Bill 
Cycles");
        listItem = oList.getItemById(id);
        clientContext.load(listItem);
        listContentTypes = oList.get_contentTypes();
        clientContext.load(listContentTypes);
        clientContext.executeQueryAsync(
            function() {
                $log.info("Successfully retrieved 
getContentTypeOfCurrentItemt");
                var ctid = listItem.get_item("ContentTypeId").toString();            
                var ct_enumerator = listContentTypes.getEnumerator();
                while (ct_enumerator.moveNext()) {
                    var ct = ct_enumerator.get_current();            
                    if (ct.get_id().toString() == ctid) {
                        var contentTypeName = ct.get_name();
                    }
                }
                resolve(contentTypeName);
           },
           function(error, errorInfo) {
                $log.warn("Retrieving getContentTypeOfCurrentItem failed");
                reject(errorInfo);
           }
        );
    });
}

addContentType也可以更容易:

function addContentType(listItem){
    return getContentTypeOfCurrentItem(listItem.ID.toString()).then(function(cname) {
        listItem['Document Type'] = cname; //we add the doc type to each listItem, not only the last one
    }).catch(function(error) {
        $log.warn("Server error");
    });
}