ฉันเห็นทั้งangular.factory ()และangular.service ()เคยประกาศบริการ อย่างไรก็ตามฉันไม่พบ angular.service
ที่ใดก็ได้ในเอกสารอย่างเป็นทางการ
ความแตกต่างระหว่างสองวิธีคืออะไร?
ควรใช้สิ่งใด (สมมติว่าพวกเขาทำสิ่งต่าง ๆ )
ฉันเห็นทั้งangular.factory ()และangular.service ()เคยประกาศบริการ อย่างไรก็ตามฉันไม่พบ angular.service
ที่ใดก็ได้ในเอกสารอย่างเป็นทางการ
ความแตกต่างระหว่างสองวิธีคืออะไร?
ควรใช้สิ่งใด (สมมติว่าพวกเขาทำสิ่งต่าง ๆ )
คำตอบ:
angular.service('myService', myServiceFunction);
angular.factory('myFactory', myFactoryFunction);
ฉันมีปัญหาห่อหัวของฉันรอบแนวคิดนี้จนกว่าฉันจะทำให้ตัวเองด้วยวิธีนี้:
บริการ : ฟังก์ชั่นที่คุณเขียนจะใหม่ -ed:
myInjectedService <---- new myServiceFunction()
Factory : ฟังก์ชั่น (นวกรรมิก) ที่คุณเขียนจะถูกเรียกใช้ :
myInjectedFactory <--- myFactoryFunction()
สิ่งที่คุณทำขึ้นอยู่กับคุณ แต่มีบางรูปแบบที่มีประโยชน์ ...
function myServiceFunction() {
this.awesomeApi = function(optional) {
// calculate some stuff
return awesomeListOfValues;
}
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.awesome = myInjectedService.awesomeApi();
function myFactoryFunction() {
var aPrivateVariable = "yay";
function hello() {
return "hello mars " + aPrivateVariable;
}
// expose a public API
return {
hello: hello
};
}
---------------------------------------------------------------------------------
// Injected in your controller
$scope.hello = myInjectedFactory.hello();
function myFactoryFunction() {
return function() {
var a = 2;
this.a2 = function() {
return a*2;
};
};
}
---------------------------------------------------------------------------------
// Injected in your controller
var myShinyNewObject = new myInjectedFactory();
$scope.four = myShinyNewObject.a2();
คุณสามารถทำสิ่งเดียวกันทั้งสองอย่างได้ อย่างไรก็ตามในบางกรณีโรงงานให้ความยืดหยุ่นเล็กน้อยในการสร้างการฉีดด้วยไวยากรณ์ที่ง่ายขึ้น นั่นเป็นเพราะในขณะที่ myInjectedService ต้องเป็นวัตถุเสมอ myInjectedFactory สามารถเป็นวัตถุการอ้างอิงฟังก์ชันหรือค่าใด ๆ ก็ได้ ตัวอย่างเช่นถ้าคุณเขียนบริการเพื่อสร้างนวกรรมิก (ดังในตัวอย่างด้านบน) มันจะต้องมีการยกตัวอย่างเช่น:
var myShinyNewObject = new myInjectedService.myFunction()
ซึ่งเนื้อหาที่ต้องการน้อยกว่านี้:
var myShinyNewObject = new myInjectedFactory();
(แต่คุณควรระวังเกี่ยวกับการใช้รูปแบบประเภทนี้ตั้งแต่แรกเพราะวัตถุที่สร้างขึ้นใหม่ในคอนโทรลเลอร์ของคุณสร้างการอ้างอิงที่ยากต่อการติดตามที่ยากต่อการจำลองการทดสอบดีกว่าที่จะให้บริการจัดการชุดของวัตถุสำหรับ คุณมากกว่าใช้new()
wily-nilly)
โปรดทราบว่าในทั้งสองกรณีแองกูลาร์กำลังช่วยคุณจัดการซิงเกิลตัน ไม่ว่าคุณจะฉีดบริการหรือฟังก์ชั่นของคุณที่ไหนหรือกี่ครั้งคุณจะได้รับการอ้างอิงเดียวกันกับวัตถุหรือฟังก์ชั่นเดียวกัน (ยกเว้นเมื่อโรงงานส่งคืนค่าเช่นตัวเลขหรือสตริงในกรณีนั้นคุณจะได้รับค่าเดิมเสมอ แต่ไม่ใช่การอ้างอิง)
new fn()
ดังนั้นพวกเขาจะต้องส่งคืน
ใส่เพียง ..
// Service
service = (a, b) => {
a.lastName = b;
return a;
};
// Factory
factory = (a, b) => Object.assign({}, a, { lastName: b });
const fullName = { firstName: 'john' };
// Service
const lastNameService = (a, b) => {
a.lastName = b;
return a;
};
console.log(lastNameService(fullName, 'doe'));
// Factory
const lastNameFactory = (a, b) =>
Object.assign({}, a, { lastName: b })
console.log(lastNameFactory(fullName, 'doe'));
นี่คือความแตกต่างหลัก:
ไวยากรณ์: module.service( 'serviceName', function );
ส่งผลให้เกิด: เมื่อประกาศ SERVICENAME เป็นอาร์กิวเมนต์ฉีดคุณจะมีให้กับอินสแตนซ์ของฟังก์ชันmodule.service
ส่งผ่านไปยัง
การใช้งาน: อาจมีประโยชน์สำหรับการแบ่งปันฟังก์ชั่นยูทิลิตี้ที่มีประโยชน์ในการเรียกใช้โดยการต่อท้าย( )
การอ้างอิงฟังก์ชั่นการฉีด อาจจะทำงานด้วยinjectedArg.call( this )
หรือคล้ายกัน
ไวยากรณ์: module.factory( 'factoryName', function );
ผล: เมื่อประกาศ factoryName เป็นอาร์กิวเมนต์ฉีดคุณจะได้รับกับค่าที่ถูกส่งกลับโดยเรียกอ้างอิงฟังก์ชันmodule.factory
ส่งผ่านไปยัง
การใช้งาน: อาจมีประโยชน์สำหรับการส่งคืนฟังก์ชัน'คลาส'ที่สามารถเป็น new'ed เพื่อสร้างอินสแตนซ์
นี่คือตัวอย่างการใช้บริการและโรงงาน อ่านเพิ่มเติมเกี่ยวกับAngularJS บริการ VS โรงงาน
นอกจากนี้คุณยังสามารถตรวจสอบเอกสาร AngularJSและคำถามที่คล้ายกันใน StackOverflow สับสนเกี่ยวกับการบริการเทียบกับโรงงาน
$providers
ตลอดเวลา
this.myFunc = function(){}
ในบริการของคุณ (ช่วยให้คุณประหยัดจากการเขียนรหัสเพื่อสร้างวัตถุเหมือนที่คุณต้องทำกับโรงงาน )
TL; DR
1)เมื่อคุณใช้Factory ที่คุณสร้างวัตถุให้เพิ่มคุณสมบัติเข้าไปจากนั้นส่งคืนวัตถุเดียวกันนั้น เมื่อคุณส่งโรงงานนี้ไปยังตัวควบคุมของคุณคุณสมบัติเหล่านั้นบนวัตถุจะมีอยู่ในตัวควบคุมนั้นผ่านโรงงานของคุณ
app.controller('myFactoryCtrl', function($scope, myFactory){
$scope.artist = myFactory.getArtist();
});
app.factory('myFactory', function(){
var _artist = 'Shakira';
var service = {};
service.getArtist = function(){
return _artist;
}
return service;
});
2)เมื่อคุณใช้บริการ Angular จะยกตัวอย่างเบื้องหลังด้วยคำหลัก 'ใหม่' ด้วยเหตุนี้คุณจะเพิ่มคุณสมบัติให้กับ 'this' และบริการจะส่งคืน 'this' เมื่อคุณส่งผ่านบริการไปยังคอนโทรลเลอร์ของคุณคุณสมบัติเหล่านี้ใน 'this' จะพร้อมใช้งานบนคอนโทรลเลอร์ดังกล่าวผ่านบริการของคุณ
app.controller('myServiceCtrl', function($scope, myService){
$scope.artist = myService.getArtist();
});
app.service('myService', function(){
var _artist = 'Nelly';
this.getArtist = function(){
return _artist;
}
});
ไม่ใช่ TL; DR
1) Factory Factory
เป็นวิธีที่นิยมที่สุดในการสร้างและกำหนดค่าบริการ ไม่มีอะไรมากไปกว่าสิ่งที่ TL; DR กล่าว คุณเพิ่งสร้างวัตถุเพิ่มคุณสมบัติเข้าไปแล้วส่งคืนวัตถุเดียวกันนั้น จากนั้นเมื่อคุณส่งโรงงานไปยังคอนโทรลเลอร์ของคุณคุณสมบัติเหล่านั้นบนวัตถุจะมีอยู่ในคอนโทรลเลอร์นั้นผ่านโรงงานของคุณ ตัวอย่างที่กว้างขวางยิ่งขึ้นอยู่ด้านล่าง
app.factory('myFactory', function(){
var service = {};
return service;
});
ตอนนี้คุณสมบัติอะไรก็ตามที่เราแนบกับ 'บริการ' จะมีให้เราเมื่อเราส่ง 'myFactory' เข้าไปในตัวควบคุมของเรา
ตอนนี้เราจะเพิ่มตัวแปร 'ส่วนตัว' ลงในฟังก์ชันการโทรกลับของเรา สิ่งเหล่านี้จะไม่สามารถเข้าถึงได้โดยตรงจากคอนโทรลเลอร์ แต่ในที่สุดเราจะตั้งค่าเมธอด getter / setter ใน 'บริการ' เพื่อให้สามารถเปลี่ยนตัวแปร 'ส่วนตัว' เหล่านี้เมื่อจำเป็น
app.factory('myFactory', function($http, $q){
var service = {};
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK';
return _finalUrl
}
return service;
});
ที่นี่คุณจะสังเกตเห็นว่าเราไม่ได้แนบตัวแปร / ฟังก์ชั่นเหล่านั้นเข้ากับ 'บริการ' เราแค่สร้างมันขึ้นมาเพื่อใช้หรือดัดแปลงในภายหลัง
ตอนนี้ผู้ช่วย / ตัวแปรส่วนตัวและฟังก์ชั่นของเราพร้อมใช้งานแล้วให้เพิ่มคุณสมบัติบางอย่างลงในออบเจ็กต์ 'บริการ' สิ่งที่เราใส่ใน 'บริการ' เราจะสามารถใช้โดยตรงในตัวควบคุมใดก็ตามที่เราส่งผ่าน 'myFactory' เข้าไป
เราจะสร้างเมธอด setArtist และ getArtist ที่เพียงแค่คืนค่าหรือตั้งค่าศิลปิน เรากำลังจะสร้างวิธีการที่จะเรียก iTunes API ด้วย URL ที่สร้างขึ้นของเรา วิธีนี้จะคืนสัญญาที่จะตอบสนองเมื่อข้อมูลได้กลับมาจาก iTunes API หากคุณยังไม่เคยมีประสบการณ์การใช้คำสัญญาใน Angular มากนักฉันขอแนะนำให้ดำน้ำลึก
ด้านล่างsetArtistยอมรับศิลปินและอนุญาตให้คุณตั้งค่าศิลปิน getArtistส่งคืนcall callItunesของศิลปินสายแรก makeUrl () เพื่อสร้าง URL ที่เราจะใช้กับคำขอ $ http ของเรา จากนั้นจะตั้งค่าวัตถุสัญญาทำให้คำขอ $ http เป็น URL สุดท้ายของเราจากนั้นเนื่องจาก $ http ส่งคืนสัญญาเราจึงสามารถโทรหา. สำเร็จหรือ .error หลังจากคำขอของเรา จากนั้นเราจะแก้ไขสัญญาของเรากับข้อมูล iTunes หรือเราปฏิเสธด้วยข้อความแจ้งว่า 'มีข้อผิดพลาด'
app.factory('myFactory', function($http, $q){
var service = {};
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
service.setArtist = function(artist){
_artist = artist;
}
service.getArtist = function(){
return _artist;
}
service.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
return service;
});
ตอนนี้โรงงานของเราเสร็จสมบูรณ์แล้ว ตอนนี้เราสามารถฉีด 'myFactory' ลงในตัวควบคุมใด ๆ แล้วเราจะสามารถเรียกวิธีการของเราที่เราแนบไปกับวัตถุบริการของเรา (setArtist, getArtist และ callItunes)
app.controller('myFactoryCtrl', function($scope, myFactory){
$scope.data = {};
$scope.updateArtist = function(){
myFactory.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myFactory.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
ในตัวควบคุมด้านบนเรากำลังทำการฉีดในบริการ 'myFactory' จากนั้นเราตั้งค่าคุณสมบัติบนวัตถุ $ scope ที่มาจากข้อมูลจาก 'myFactory' โค้ดที่ยุ่งยากเพียงอย่างเดียวด้านบนคือหากคุณไม่เคยทำสัญญากับคุณมาก่อน เนื่องจาก callItunes ส่งคืนสัญญาเราจึงสามารถใช้วิธีการ. then () และตั้งค่า $ scope.data.artistData เพียงครั้งเดียวเมื่อสัญญาของเราได้รับการปฏิบัติตามข้อมูล iTunes คุณจะสังเกตเห็นว่าคอนโทรลเลอร์ของเรานั้น 'บาง' มาก ตรรกะและข้อมูลถาวรทั้งหมดของเราตั้งอยู่ในบริการของเราไม่ใช่ในตัวควบคุมของเรา
2) บริการ
บางทีสิ่งที่สำคัญที่สุดที่ควรทราบเมื่อต้องจัดการกับการสร้างบริการคือการสร้างอินสแตนซ์ของคำหลัก 'ใหม่' สำหรับคุณ gurus JavaScript คุณควรให้คำแนะนำอย่างละเอียดเกี่ยวกับลักษณะของรหัส สำหรับผู้ที่มีพื้นหลังที่ จำกัด ใน JavaScript หรือสำหรับผู้ที่ไม่คุ้นเคยกับสิ่งที่คำหลัก 'ใหม่' จริงลองมาตรวจทานพื้นฐาน JavaScript ที่จะช่วยเราในการทำความเข้าใจลักษณะของบริการ
หากต้องการดูการเปลี่ยนแปลงที่เกิดขึ้นเมื่อคุณเรียกใช้ฟังก์ชันด้วยคำหลัก 'ใหม่' ให้สร้างฟังก์ชันและเรียกใช้ด้วยคำหลัก 'ใหม่' จากนั้นให้แสดงสิ่งที่ล่ามทำเมื่อเห็นคำหลัก 'ใหม่' ผลลัพธ์ที่ได้จะเหมือนกันทั้งคู่
ก่อนอื่นมาสร้างตัวสร้างของเรา
var Person = function(name, age){
this.name = name;
this.age = age;
}
นี่คือฟังก์ชันตัวสร้าง JavaScript ทั่วไป ตอนนี้เมื่อใดก็ตามที่เราเรียกใช้ฟังก์ชั่นบุคคลโดยใช้คำหลัก 'ใหม่' นี้จะถูกผูกไว้กับวัตถุที่สร้างขึ้นใหม่
ตอนนี้เราจะเพิ่มวิธีการลงบนต้นแบบของบุคคลของเราเพื่อให้สามารถใช้ได้กับทุก ๆ ตัวอย่างของ 'ชั้นเรียน' ของบุคคล
Person.prototype.sayName = function(){
alert('My name is ' + this.name);
}
ตอนนี้เนื่องจากเราใส่ฟังก์ชั่น sayName ลงบนต้นแบบทุกอินสแตนซ์ของ Person จะสามารถเรียกใช้ฟังก์ชัน sayName เพื่อแจ้งเตือนการสั่งซื้อชื่อของอินสแตนซ์นั้น
ตอนนี้เรามีฟังก์ชั่นตัวสร้างบุคคลของเราและฟังก์ชั่น sayName ของเราบนต้นแบบแล้วลองสร้างตัวอย่างของบุคคลจากนั้นเรียกใช้ฟังก์ชั่น sayName
var tyler = new Person('Tyler', 23);
tyler.sayName(); //alerts 'My name is Tyler'
ดังนั้นทุกรหัสเข้าด้วยกันสำหรับการสร้างตัวสร้างบุคคลเพิ่มฟังก์ชั่นของมันเป็นต้นแบบสร้างอินสแตนซ์ของบุคคลแล้วเรียกฟังก์ชั่นบนต้นแบบของมันมีลักษณะเช่นนี้
var Person = function(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
alert('My name is ' + this.name);
}
var tyler = new Person('Tyler', 23);
tyler.sayName(); //alerts 'My name is Tyler'
ตอนนี้เรามาดูสิ่งที่เกิดขึ้นจริงเมื่อคุณใช้คำหลัก 'ใหม่' ใน JavaScript สิ่งแรกที่คุณควรสังเกตคือหลังจากใช้ 'ใหม่' ในตัวอย่างของเราเราสามารถเรียกเมธอด (sayName) บน 'tyler' เหมือนกับว่ามันเป็นวัตถุ - นั่นเป็นเพราะมันเป็น ดังนั้นก่อนอื่นเรารู้ว่าตัวสร้างบุคคลของเราส่งคืนวัตถุไม่ว่าเราจะเห็นว่าในโค้ดหรือไม่ ประการที่สองเรารู้ว่าเนื่องจากฟังก์ชั่น sayName ของเราตั้งอยู่บนต้นแบบและไม่ได้อยู่บนอินสแตนซ์ Person โดยตรงวัตถุที่ฟังก์ชัน Person กำลังส่งคืนจะต้องมอบสิทธิ์ให้กับต้นแบบในการค้นหาที่ล้มเหลว ในแง่ง่ายขึ้นเมื่อเราเรียก tyler.sayName () ล่ามบอกว่า“ ตกลงฉันจะดูที่วัตถุ 'tyler' ที่เราเพิ่งสร้างขึ้นค้นหาฟังก์ชัน sayName แล้วเรียกมัน เดี๋ยวก่อนฉันไม่เห็นที่นี่ - ทั้งหมดที่ฉันเห็นคือชื่อและอายุ ให้ฉันตรวจสอบต้นแบบ ใช่ดูเหมือนว่ามันอยู่บนต้นแบบให้ฉันเรียกมันว่า”
ด้านล่างคือรหัสสำหรับวิธีที่คุณสามารถคิดเกี่ยวกับสิ่งที่คำหลัก 'ใหม่' ทำงานจริงใน JavaScript มันเป็นตัวอย่างรหัสของย่อหน้าข้างต้น ฉันใส่ 'มุมมองล่าม' หรือวิธีที่ล่ามเห็นโค้ดในบันทึกย่อ
var Person = function(name, age){
//The line below this creates an obj object that will delegate to the person's prototype on failed lookups.
//var obj = Object.create(Person.prototype);
//The line directly below this sets 'this' to the newly created object
//this = obj;
this.name = name;
this.age = age;
//return this;
}
ตอนนี้มีความรู้ในสิ่งที่คำหลัก 'ใหม่' นี้จริงๆใน JavaScript การสร้างบริการในเชิงมุมควรจะเข้าใจง่ายขึ้น
สิ่งที่ใหญ่ที่สุดที่ควรทำความเข้าใจเมื่อสร้างบริการคือการรู้ว่าบริการได้รับการยกตัวอย่างด้วยคำหลัก 'ใหม่' เมื่อรวมความรู้ดังกล่าวกับตัวอย่างของเราข้างต้นแล้วคุณควรตระหนักว่าคุณกำลังแนบคุณสมบัติและวิธีการของคุณโดยตรงกับ 'นี้' ซึ่งจะส่งคืนจากบริการ ลองดูที่การทำงานนี้
ซึ่งแตกต่างจากที่เราทำกับตัวอย่างโรงงานในตอนแรกเราไม่จำเป็นต้องสร้างวัตถุจากนั้นคืนค่าวัตถุนั้นเพราะอย่างที่เคยกล่าวไว้หลายครั้งก่อนหน้านี้เราใช้คำหลัก 'ใหม่' เพื่อที่ล่ามจะสร้างวัตถุนั้น มันเป็นต้นแบบแล้วส่งคืนให้เราโดยที่เราไม่ต้องทำงาน
ก่อนอื่นมาสร้างฟังก์ชั่น 'ส่วนตัว' และตัวช่วยของเรา สิ่งนี้ควรดูคุ้นเคยเพราะเราทำสิ่งเดียวกันกับโรงงานของเรา ฉันจะไม่อธิบายว่าแต่ละบรรทัดทำอะไรที่นี่เพราะฉันทำอย่างนั้นในตัวอย่างจากโรงงานถ้าคุณงงให้อ่านตัวอย่างจากโรงงานอีกครั้ง
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
});
ตอนนี้เราจะแนบวิธีการทั้งหมดของเราที่จะมีอยู่ในตัวควบคุมของเรากับ 'นี้'
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
this.setArtist = function(artist){
_artist = artist;
}
this.getArtist = function(){
return _artist;
}
this.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
});
ตอนนี้เหมือนในโรงงานของเรา setArtist, getArtist และ callItunes จะมีอยู่ในตัวควบคุมใดก็ตามที่เราส่งผ่าน myService ไป นี่คือตัวควบคุม myService (ซึ่งเกือบจะเหมือนกับตัวควบคุมโรงงานของเรา)
app.controller('myServiceCtrl', function($scope, myService){
$scope.data = {};
$scope.updateArtist = function(){
myService.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myService.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
อย่างที่ฉันเคยพูดเมื่อคุณเข้าใจสิ่งที่ 'ใหม่' ทำบริการเกือบจะเหมือนโรงงานใน Angular
บริการและโรงงานมีความคล้ายคลึงกัน ทั้งสองจะให้ผลลัพธ์วัตถุเดี่ยวที่สามารถฉีดเข้าไปในวัตถุอื่น ๆ และมักจะใช้แทนกันได้
พวกเขาตั้งใจที่จะใช้ความหมายในการใช้รูปแบบการออกแบบที่แตกต่างกัน
รูปแบบการบริการเป็นสิ่งหนึ่งที่แอปพลิเคชันของคุณแบ่งออกเป็นฟังก์ชันการทำงานที่สอดคล้องตามหลักเหตุผล ตัวอย่างอาจเป็นตัวเข้าถึง API หรือชุดของตรรกะทางธุรกิจ
สิ่งนี้มีความสำคัญอย่างยิ่งในแองกูลาร์เนื่องจากโมเดลของแองกูลาร์มักจะเป็นเพียงวัตถุ JSON ที่ดึงมาจากเซิร์ฟเวอร์ดังนั้นเราจึงต้องการที่อื่นเพื่อวางตรรกะทางธุรกิจของเรา
นี่คือบริการ Github เช่น มันรู้วิธีคุยกับ Github มันรู้เกี่ยวกับ URL และวิธีการ เราสามารถอัดมันเข้าไปในคอนโทรลเลอร์และมันจะสร้างและคืนสัญญา
(function() {
var base = "https://api.github.com";
angular.module('github', [])
.service('githubService', function( $http ) {
this.getEvents: function() {
var url = [
base,
'/events',
'?callback=JSON_CALLBACK'
].join('');
return $http.jsonp(url);
}
});
)();
ในทางกลับกันโรงงานมีจุดประสงค์เพื่อใช้รูปแบบของโรงงาน รูปแบบของโรงงานที่เราใช้ฟังก์ชั่นจากโรงงานเพื่อสร้างวัตถุ โดยทั่วไปแล้วเราอาจใช้สิ่งนี้สำหรับสิ่งปลูกสร้าง นี่คือโรงงานที่ส่งคืน Constructor ของผู้แต่ง:
angular.module('user', [])
.factory('User', function($resource) {
var url = 'http://simple-api.herokuapp.com/api/v1/authors/:id'
return $resource(url);
})
เราจะใช้ประโยชน์จากสิ่งนี้เช่นนั้น:
angular.module('app', ['user'])
.controller('authorController', function($scope, User) {
$scope.user = new User();
})
โปรดทราบว่าโรงงานจะส่งคืนซิงเกิลตันด้วย
เนื่องจากโรงงานส่งคืนวัตถุก็สามารถส่งคืนวัตถุประเภทใดก็ได้ที่คุณต้องการรวมถึงฟังก์ชันตัวสร้างตามที่เราเห็นด้านบน
ความแตกต่างทางเทคนิคอีกประการหนึ่งก็คือวิธีการให้บริการและโรงงานประกอบ ฟังก์ชั่นบริการจะถูกสร้างขึ้นใหม่เพื่อสร้างวัตถุ ฟังก์ชั่นจากโรงงานจะถูกเรียกและจะคืนค่าวัตถุ
ซึ่งหมายความว่าในบริการเราผนวกเข้ากับ "สิ่งนี้" ซึ่งในบริบทของตัวสร้างจะชี้ไปที่วัตถุที่อยู่ระหว่างการก่อสร้าง
เพื่อแสดงให้เห็นสิ่งนี้นี่เป็นวัตถุง่าย ๆ ที่สร้างขึ้นโดยใช้บริการและโรงงาน:
angular.module('app', [])
.service('helloService', function() {
this.sayHello = function() {
return "Hello!";
}
})
.factory('helloFactory', function() {
return {
sayHello: function() {
return "Hello!";
}
}
});
Author
Person
คำตอบทั้งหมดที่นี่ดูเหมือนจะเป็นรอบการบริการและโรงงานและที่ถูกต้องตั้งแต่นั้นเป็นสิ่งที่ถูกถามเกี่ยวกับ แต่มันก็ยังเป็นสิ่งสำคัญที่จะเก็บไว้ในใจว่ามีคนอื่น ๆ หลายคนรวมทั้งprovider()
, และvalue()
constant()
กุญแจสำคัญในการจำคือแต่ละคนเป็นกรณีพิเศษของอีกคนหนึ่ง แต่ละกรณีพิเศษลงโซ่ช่วยให้คุณทำสิ่งเดียวกันกับรหัสน้อย แต่ละคนมีข้อ จำกัด เพิ่มเติมบางอย่างเช่นกัน
ในการตัดสินใจว่าจะใช้เมื่อใดซึ่งคุณเพิ่งเห็นว่าอันไหนให้คุณทำสิ่งที่คุณต้องการในโค้ดที่น้อยกว่า นี่คือภาพที่แสดงให้เห็นว่ามีความคล้ายคลึงกันอย่างไร:
สำหรับการแยกทีละขั้นตอนอย่างสมบูรณ์และการอ้างอิงอย่างรวดเร็วว่าจะใช้เมื่อใดคุณสามารถไปที่โพสต์บล็อกที่ฉันได้รับภาพนี้จาก:
การก่อสร้าง
สำหรับโรงงาน Angular จะเรียกใช้ฟังก์ชันเพื่อรับผลลัพธ์ เป็นผลลัพธ์ที่ถูกแคชและฉีด
//factory
var obj = fn();
return obj;
ด้วยบริการเชิงมุมจะเรียกฟังก์ชั่นคอนสตรัคโดยการเรียกใหม่ ฟังก์ชั่นที่สร้างขึ้นจะถูกแคชและฉีด
//service
var obj = new fn();
return obj;
การดำเนินงาน
โดยทั่วไปโรงงานจะส่งคืนวัตถุตามตัวอักษรเนื่องจากค่าส่งคืนคือสิ่งที่ถูกฉีดเข้าไปในตัวควบคุมเรียกใช้บล็อกคำสั่ง ฯลฯ
app.factory('fn', function(){
var foo = 0;
var bar = 0;
function setFoo(val) {
foo = val;
}
function setBar (val){
bar = val;
}
return {
setFoo: setFoo,
serBar: setBar
}
});
ฟังก์ชั่นบริการมักจะไม่ส่งคืนสิ่งใด แต่จะดำเนินการเตรียมใช้งานและแสดงฟังก์ชันแทน ฟังก์ชั่นยังสามารถอ้างอิง 'นี่' ได้เนื่องจากมันถูกสร้างโดยใช้ 'ใหม่'
app.service('fn', function () {
var foo = 0;
var bar = 0;
this.setFoo = function (val) {
foo = val;
}
this.setBar = function (val){
bar = val;
}
});
ข้อสรุป
เมื่อมาถึงการใช้โรงงานหรือบริการพวกเขาทั้งสองคล้ายกันมาก พวกเขาจะถูกฉีดเข้าไปในตัวควบคุมคำสั่งเรียกใช้บล็อก ฯลฯ และใช้ในรหัสลูกค้าในลักษณะเดียวกัน ทั้งสองแบบยังเป็นแบบซิงเกิล - หมายถึงอินสแตนซ์เดียวกันจะถูกใช้ร่วมกันระหว่างทุกสถานที่ที่ให้บริการ / โรงงาน
คุณควรเลือกแบบไหนดี? อย่างใดอย่างหนึ่ง - พวกเขาคล้ายกันมากกับความแตกต่างเล็กน้อย หากคุณเลือกอย่างใดอย่างหนึ่งเพียงแค่ตระหนักถึงวิธีการสร้างพวกเขาเพื่อให้คุณสามารถใช้พวกเขาอย่างถูกต้อง
ฉันใช้เวลาพยายามหาความแตกต่าง
และฉันคิดว่าฟังก์ชั่นจากโรงงานใช้รูปแบบโมดูลและฟังก์ชั่นบริการใช้รูปแบบตัวสร้างสคริปต์จาวามาตรฐาน
รูปแบบของโรงงานมีความยืดหยุ่นมากขึ้นเนื่องจากสามารถส่งคืนฟังก์ชั่นและค่าเช่นเดียวกับวัตถุ
รูปแบบการบริการมีไม่มาก IMHO เหมือนทุกสิ่งที่คุณสามารถทำได้อย่างง่ายดายเช่นเดียวกับโรงงาน ข้อยกเว้นอาจเป็น:
รูปแบบการบริการคือ วิธีที่ดีกว่าเล็กน้อยในการสร้างออบเจ็กต์ใหม่จากมุมมองไวยากรณ์ แต่ก็มีค่าใช้จ่ายสูงกว่าในการสร้างอินสแตนซ์ คนอื่น ๆ ระบุว่าเชิงมุมใช้ "ใหม่" เพื่อสร้างบริการ แต่สิ่งนี้ไม่เป็นความจริง - มันไม่สามารถทำได้เพราะผู้ให้บริการทุกคนมีพารามิเตอร์ที่แตกต่างกัน สิ่งที่เชิงมุมทำคือใช้รูปแบบจากโรงงานเพื่อห่อฟังก์ชันตัวสร้างของคุณ จากนั้นมันจะทำ jiggery pokery ที่ชาญฉลาดเพื่อจำลองโอเปอเรเตอร์ "ใหม่" ของ javascript ซึ่งเรียกใช้คอนสตรัคเตอร์ของคุณด้วยจำนวนตัวแปรที่สามารถฉีดได้ - แต่คุณสามารถออกจากขั้นตอนนี้ได้ถ้าคุณใช้รูปแบบจากโรงงานโดยตรง รหัส.
function MyFactory(dep1) { var $$foo = 'bar', factory = {}; Object.defineProperties(factory.prototype, { foo: { value: $$foo } }); return factory; }
function MyService(dep1) { var $$foo = 'bar'; Object.defineProperties(MyService.prototype, { foo: { value: $$foo } }); }
ในขณะที่ทั้ง MyFactory และ MyService ใช้ต้นแบบ MyFactory ยังคงต้องใช้ประสิทธิภาพในการสร้างวัตถุที่ถูกส่งคืน ในทั้งสองตัวอย่างพวกเขามีเอกชน แต่ใน MyService ไม่มีความแตกต่างด้านประสิทธิภาพ
MyFactory(someArgument)
(อดีต$http()
) MyService(someArgument)
ว่าเป็นไปไม่ได้ที่มีบริการตามที่คุณต้องการจะสร้างอ้างอิง: