Javascript TypeError:无法调用方法';然后';未定义角度的定义
我对Angular很陌生,在同步操作方面有问题。我已经解决了一些关于angular controller的问题,从newController文件中抛出了错误“Cannot call method of undefined”Javascript TypeError:无法调用方法';然后';未定义角度的定义,javascript,angularjs,promise,Javascript,Angularjs,Promise,我对Angular很陌生,在同步操作方面有问题。我已经解决了一些关于angular controller的问题,从newController文件中抛出了错误“Cannot call method of undefined” angular.module('newApp.newController', ['angularSpinner', 'ui.bootstrap']) .controller('newController', function($q, $scope, utilityFacto
angular.module('newApp.newController', ['angularSpinner', 'ui.bootstrap'])
.controller('newController', function($q, $scope, utilityFactory, $http) {
utilityFactory.getData().then(function(data) {
console.log("success");
console.log(data);
});
});
angular.module('newApp.utility', [])
.factory('utilityFactory', function($q, $http) {
var utils = {};
//This is a cordova plugin
var getLauncher = function() {
return window.plugin.launcher;
};
var success = function(data) {
console.log(device);
return device;
}
var fail = function(error) {
console.log("error", error);
};
utils.getData = function() {
/* Get the store number details initially before initalizing the application */
if (window.plugin) {
var launcher = getLauncher();
console.log("Fetching data from device");
//Cordova js is returning this method
return launcher.getDevice(success, fail);
}
};
return utils;
})
这句话就是问题所在,我只想用一个承诺来结束它:
return $q(launcher.getDevice.bind(launcher, success, fail));
编辑:您还需要考虑其他条件,因此代码为:
utils.getData = function() {
/* Get the store number details initially before initalizing the application */
if (window.plugin) {
var launcher = getLauncher();
console.log("Fetching data from device");
//Cordova js is returning this method
return $q(launcher.getDevice.bind(launcher, success, fail));
}
return $q.resolve(); // or $q.reject(reason);
};
了解到:
Launcher.prototype.getDevice = function(successCallback, failureCallback) {
exec(successCallback, failureCallback, KEY, 'getDevice', []);
}
,我们知道window.plugin.launcher.getDevice()
返回的是未定义的
,而不是数据对象。相反,它通过成功/失败回调提供响应
因此,要使用承诺,window.plugin.launcher.getDevice()
需要“promisified”,包括显式创建一个新承诺()
,并通过.getDevice的回调来解决/拒绝它。(简单地用$q(…)包装是两码事,也行不通)
从控制器调用现在应该可以工作了:
angular.module('newApp.newController', ['angularSpinner', 'ui.bootstrap']).controller('newController', function($q, $scope, utilityFactory, $http) {
return utilityFactory.getDevice().then(function(data) {
console.log(data);
}).catch(function(error) {
console.error(error);
});
});
1) 实际模块应该是“newApp”,而不是“newApp.newController”和“newApp.utility”。也就是说,将这两个组件放在单独的模块中,而不是放在myApp模块中
2) 您应该只使用
angular.module('newApp', [])
无论何时声明新模块。当您想访问该模块时,应使用
angular.module('newApp')
3) utilityFactory返回的变量“device”未在任何地方声明
4) 如果不在getData函数中返回承诺,则不能使用“then”。然后是一个用Javascript实现的方法,所以不能在代码中的任何地方使用它。
这是我调试代码时使用的代码笔。我稍微修改了您的代码,但它将给出一个函数在返回承诺时工作的示例 正如前面提到的一些其他答案一样,您需要从
utils.getData
函数返回一个Promise
。Angular的$q
帮助程序允许您这样做。然而,其他一些答案向您展示的方法与最佳实践背道而驰。使用$q
时,最佳做法是执行以下操作:
var myPromise = $q(function (resolve, reject) {
// Do some logic in here that is asynchronous and either invoke resolve with
// the results or reject with an error that may have occurred
});
angular.module('newApp.newController', ['angularSpinner', 'ui.bootstrap', 'newApp.utility'])
// Make sure to add 'newApp.utility' to the dependencies of the 'newApp.newController' module.
因此,您的代码变成:
angular.module('newApp.utility', [])
.factory('utilityFactory', function($q, $http) {
var utils = {};
//This is a cordova plugin
var getLauncher = function() {
return window.plugin.launcher;
};
var success = function(data) {
console.log(device);
return device;
}
var fail = function(error) {
console.log("error", error);
};
utils.getData = function() {
/* Get the store number details initially before initalizing the application */
return $q(function (resolve, reject) {
if (!window.plugin) {
// You can handle this case as a rejection of the promise
reject(new Error('Window plugin not found'));
return;
}
var launcher = getLauncher();
console.log("Fetching data from device");
//Cordova js is returning this method
// When device is ready it will "resolve" the promise and
// invoke any of the ".then()" functions you add to the promise
// If an error occurs, it will invoke any ".catch()" functions
// that you have added.
launcher.getDevice(resolve, reject);
});
};
return utils;
})
有关$q
服务的更多信息,请查看AngularJS官方文档中的这篇文章:
$q
另外,如果您想了解有关JavaScript中的承诺和异步编程的更多信息,请参阅以下参考资料:
整洁的承诺可视化工具-
承诺教程-
作为AngularJS最佳实践的一般指南,另一个需要研究的是John Papa的AngularJS风格指南:
最后,您设置模块的方式有点偏离。每次调用angular.module(moduleName,dependencies)
都将创建一个具有这些依赖项的新模块。虽然将angular应用程序分解为多个模块是个好主意,但您需要确保您的根或“main”使用ng app
指令引用的应用程序引用了您的所有子模块,并且引用其他模块依赖项的任何模块都将该模块包含在其依赖项列表中
在您的情况下,您创建了一个名为newApp.newController
的模块,但由于它试图引用utilityFactory
,该工厂在名为newApp.utility
的单独模块中定义,但未被newApp.newController
模块引用,因此无法工作。要解决此问题,请执行以下操作:
var myPromise = $q(function (resolve, reject) {
// Do some logic in here that is asynchronous and either invoke resolve with
// the results or reject with an error that may have occurred
});
angular.module('newApp.newController', ['angularSpinner', 'ui.bootstrap', 'newApp.utility'])
// Make sure to add 'newApp.utility' to the dependencies of the 'newApp.newController' module.
或者,您可以在同一模块中创建控制器和实用程序工厂:
// Create the module once
angular.module('newApp', ['angularSpinner', 'ui.bootstrap']);
// Reference it by invoking it with just one parameter
angular.module('newApp').controller('newController', ...);
angular.module('newApp').factory('utilityFactory', ...);
角度模块系统的使用和最佳实践可在以下位置找到:
getData
没有返回我使用过的任何东西,也返回launcher.getDevice(成功,失败);但是它不会为else
返回任何内容,那么launcher.getDevice
返回什么?launcher.prototype.getDevice=function(successCallback,failureCallback){exec(successCallback,failureCallback,KEY,'getDevice',[]);};'launcher.getDevice'从android手机返回与设备相关的信息,如macIdI将对此进行检查。尝试此操作后,调用getDevice方法后,它进入错误回调函数并打印消息-“错误”通过传递Promise的resolve
和reject
函数作为window.plugin.launcher.getDevice()
的successCallback和errorCallback的ReferenceError:Promise未定义“得到这个错误哇,我假设是ES6 promises。尝试同样的$q承诺。ie返回$q.defer(函数(解析,拒绝){…})代码>这样它不工作,也不会抛出任何错误。但是简单地说,响应没有到达exec(successCallback,failureCallback,KEY,'getDevice',[])的控制器的范围代码>某个地方记录的命令?
// Create the module once
angular.module('newApp', ['angularSpinner', 'ui.bootstrap']);
// Reference it by invoking it with just one parameter
angular.module('newApp').controller('newController', ...);
angular.module('newApp').factory('utilityFactory', ...);