پروژههای کوچک عموما دارای ساختاری مشابه تصویر ذیل میباشند:
این مورد، روش پیشنهادی در Angular Seed است و بدین صورت است که تعاریف ماژولها در فایل app.js انجام میگیرد. تعاریف و پیاده سازی تمام کنترلرها در فایل controller.js است. و همچنین دایرکتیوها و فیلترها و سرویسها هر کدام در فایلها جداگانه تعریف و پیاده سازی میشوند. این روش راه حلی سریع برای پروژههای کوچک با تعداد developerهای کم است. برای مثال زمانی که یک developer در حال ویرایش فایل controller.js است، از آن جا که فایل مورد نظر checkout خواهد شد در نتیجه سایر developerها امکان تغییر در فایل مورد نظر را نخواهند داشت. سورس فایلها به مرور زیاد خواهد شد و در نتیجه debug آن سخت میشود.
روش دوم
در این حالت تعاریف کنترلر ها، مدلها و سرویسها هرکدام در یک دایرکتوری مجزا قرار خواهد گرفت. برای هر view یک کنترلر و بنا بر نیاز مدل تعریف میکنیم. ساختار آن به صورت زیر میشود:
دایرکتیوها و فیلترها عموما در یک فایل قرار داده خواهند شد تا بنابر نیاز در جای مناسب رفرنس داده شوند. این روش ساختار مناسبتری نسبه به روش قبلی دارد اما دارای معایبی هم چون موارد زیر است:
»وابستگی بین فایلها مشخص نیست در نتیجه بدون استفاده از کتابخانه هایی نظیر requireJs با مشکل مواجه خواهید شد.
»refactoring کدها تا حدودی سخت است.
روش سوم
این ساختار مناسب برای پیاده سازی پروژهها به صورت ماژولار است و برای پروژههای بزرگ نیز بسیار مناسب است. در این حالت شما فایلهای مربوط به هر ماژول را در دایرکتوری خاص آن قرار خواهید داد. به صورت زیر:
همان طور که ملاحظه میکنید سرویس ها، کنترلرها و حتی مدلهای مربوط به هر بخش در یک مسیر جداگانه قرار میگیرند. علاوه بر آن فایل هایی که قابلیت اشتراکی دارند در مسیری به نام common وجود دارند تا بتوان در جای مناسب برای استفاده از آنها رفرنس داده شود. حتی اگر در پروژه خود فقط یک ماژول دارید باز سعی کنید از این روش برای مدیریت فایلهای خود استفاده نمایید. اگر با ngStart آشنایی داشته باشید به احتمال زیاد با این روش بیگانه نیستید.
بررسی چند نکته درباره کدهای مشترک
»اگر ماژولها وابستگی شدیدی به فایلها و سورسهای مشترک دارند باید اطمینان حاصل نمایید که این ماژولها فقط به اطلاعات مورد نیاز دسترسی دارند. این اصل interface segregation principle اصول SOLID است.
»توابعی که کاربرد زیادی دارند و اصطلاحا به عنوان Utility شناخته میشوند باید به rootScope$ اضافه شوند تا scopeهای وابسته نیز به آنها دسترسی داشته باشند. این مورد به ویژه باعث کاهش تکرار وابستگیهای مربوط به هر کنترلر میشود.
»برای جداسازی وابستگیهای بین دو component بهتر از eventها استفاده نمایید. AngularJs این امکان را با استفاده از سرویسهای on$ و emit$ و broadcast$ به راحتی میسر کرده است.
برای به درست آوردن این اعتماد، یکی از بالاترین الویت ها، آینده نگری معماری نرم افزار و ساخت یک معماری داده است که باید هر دو قوی و به اندازه کافی ایمن باشد، این دو برای راضی کردن مستاجران و کلاینت هایی که علاقمند هستند کنترل دادههای حیاتی تجارت خود را به شخص سومی واگذار نمایند، موثر است در حالی که برای اداره کردن و نگهداری مقرون به صرفه است.
سه روش مدیریت چند مستاجری داده
- دیتابیسهای جداگانه برای هر مستاجر
- دیتابیس مشترک و schema جداگانه برای هر مستاجر
- دیتابیس مشترک و schema مشترک
انتخاب روش مناسب برای برنامه شما به عوامل زیر بستگی دارد :
- سایز دیتابیس هر مستاجر
- تعداد مستاجران
- تعداد کاربران هر مستاجر
- نرخ رشد مستاجر
- نرخ رشد دیتابیس مستاجر
- امنیت
- هزینه
1) دیتابیسهای جداگانه برای هر مستاجر :
ذخیره سازی دادههای مستاجران در دیتابیسهای جداگانه سادهترین روش است. در این روش هر مستاجر یک دیتابیس دارد. منابع و کدهای برنامه معمولا در سرور بین همه مستاجران مشترک است اما هر مستاجر مجموعه ای از داده دارد که بطور منطقی از سایر مستاجران جدا شده است.
مزایا :
- امنیت بیشتر
- سهولت سفارشی سازی برای هر مستاجر
- سهولت نگهداری ( Backup و Restore ) برای هر مستاجر
معایب:
- برای نگهداری سخت افزار قوی مورد نیاز است
- این روش هزینه بیشتری برای تجهیزات ( Backup و Restore ) برای هر مستاجر دارد
2) دیتابیس مشترک و schema جداگانه برای هر مستاجر :
خدمات دهی به چندین مستاجر در یک دیتابیس مشترک اما هر مستاجر یک مجموعه از جداول گروهبندی شده دارد که با Schema جدا شده است که برای هر مستاجر الزامی است.
مزایا :
- برای دیتابیس برنامههای کوچک مناسب است. وقتی تعداد جداول برای هر مشتری کم است
- هزینه کمتری نسبت به روش اول دارد
- برای مشتریانی که نگران امنیت هستند، سطح منطقی مناسبی برای جداسازی داده ه وجود دارد
معایب:
- اطلاعات مستاجران در صورت بروز خطا به سختی restore میشود
- مدیریت آن برای دیتابیسهای بزرگ مشکل است
3) دیتابیس مشترک و schema مشترک :
این روش شمامل یک دیتابیس و یک مجموعه از جداول برای چندین مستاجر است. دادههای جدول میتواند شامل رکوردهای هر مستاجر باشد
مزایا :
- در مقایسه با روش قبلی، کمترین هزینه سخت افزاری را دارد
- میتواند مستاجران بیشتری رادر هر سرور پشتیبانی کند
- قابلیت بروز رسانی آسان در یک جا برای همه مستاجران
- مدیریت آسان دیتابیس و خطا و Backup و Restore
- امنیت بیشتری مورد نیاز است تا مطمئن شوید هیچکس به اطلاعات سایر مستاجران دسترسی ندارد.
- میتواند روی کارایی کوئریها تاثیر بگذارد چون تعداد رکوردها زیاد است.
- بروزرسانی و سفارشی کردن فقط برای یک مستاجر سخت است
منابع :
http://msdn.microsoft.com/en-us/library/aa479086.aspx
http://www.codeproject.com/Articles/51334/Multi-Tenants-Database-Architecture
{ "manifest_version": 2, "name": "Dotnettips Updater", "description": "This extension keeps you updated on current activities on dotnettips.info", "version": "1.0", "icons": { "16": "icon.png", "48": "icon.png", "128": "icon.png" }, "browser_action": { "default_icon": "icon.png", "default_popup": "popup.html" }, "permissions": [ "activeTab", "https://www.dntips.ir" ] }
"default_icon": { // optional "19": "images/icon19.png", // optional "38": "images/icon38.png" // optional }
صفحات پسزمینه
- صفحات مصر یا Persistent Page
- صفحات رویدادگرا یا Events Pages
"background": { "scripts": ["background.js"], "persistent": false }
Content Script یا اسکریپت محتوا
"content_scripts": [ { "matches": ["http://*/*", "https://*/*"], "js": ["content.js"] } ]
آغاز کدنویسی (رابطهای کاربری)
اجازه دهید بقیه موارد را در حین کدنویسی تجربه کنیم و هر آنچه ماند را بعدا توضیح خواهیم داد. در اینجا من از یک صفحه با کد HTML زیر بهره برده ام که یک فرم دارد به همراه چهار چک باکس و در نهایت یک دکمه جهت ذخیره مقادیر. نام صفحه را popup.htm گذاشته ام و یک فایل popup.js هم دارم که در آن کد jquery نوشتم. قصد من این است که بتوان یک action browser به شکل زیر درست کنم:
کد html آن به شرح زیر است:
<html> <head> <meta charset="utf-8"/> <script src="jquery.min.js"></script> <!-- Including jQuery --> <script type="text/javascript" src="popup.js"></script> </head> <body style="direction:rtl;width:250px;"> <form > <input type="checkbox" id="chkarticles" value="" checked="true">آخرین مطالب سایت</input><br/> <input type="checkbox" id="chkarticlescomments" value="" >آخرین نظرات مطالب سایت</input><br/> <input type="checkbox" id="chkshares" value="" >آخرین اشتراکهای سایت</input><br/> <input type="checkbox" id="chksharescomments" value="" >آخرین نظرات اشتراکهای سایت</input><br/> <input id="btnsave" type="button" value="ذخیره تغییرات" /> <div id="messageboard" style="color:green;"></div> </form> </body> </html>
$(document).ready(function () { $("#btnsave").click(function() { var articles = $("#chkarticles").is(':checked'); var articlesComments = $("#chkarticlescomments").is(':checked'); var shares = $("#chkshares").is(':checked'); var sharesComments = $("#chksharescomments").is(':checked'); chrome.storage.local.set({ 'articles': articles, 'articlesComments': articlesComments, 'shares': shares, 'sharesComments': sharesComments }, function() { $("#messageboard").text( 'تنظیمات جدید اعمال شد'); }); }); });
"permissions": [ "storage" ]
chrome.storage.sync.set
{ "manifest_version": 2, "name": "Dotnettips Updater", "description": "This extension keeps you updated on current activities on dotnettips.info", "version": "1.0", "browser_action": { "default_icon": "icon.png", "default_popup": "popup.html" }, "permissions": [ "storage" ] }
chrome://extensions
chrome.storage.local.get(['articles', 'articlesComments', 'shares', 'sharesComments'], function ( items) { console.log(items[0]); $("#chkarticles").attr("checked", items["articles"]); $("#chkarticlescomments").attr("checked", items["articlesComments"]); $("#chkshares").attr("checked", items["shares"]); $("#chksharescomments").attr("checked", items["sharesComments"]); });
"page_action": { "default_icon": { "19": "images/icon19.png", "38": "images/icon38.png" }, "default_popup": "popup.html"
"background": { "scripts": ["page_action_validator.js"] }
function UrlValidation(tabId, changeInfo, tab) { if (tab.url.indexOf('dotnettips.info') >-1) { chrome.pageAction.show(tabId); } }; chrome.tabs.onUpdated.addListener(UrlValidation);
"omnibox": { "keyword" : ".net" }
"background": { "scripts": ["omnibox.js"]
chrome.omnibox.onInputChanged.addListener(function(text, suggest) { suggest([ {content: ".net tips Home Page", description: "صفحه اصلی"}, {content: ".net tips Posts", description: "آخرین مطالب"}, {content: ".net tips News", description: "آخرین نظرات مطالب"}, {content: ".net tips Post Comments", description: "آخرین اشتراک ها"}, {content: ".net tips News Comments", description: "آخرین نظرات اشتراک ها"} ]); });
onInputStarted | بعد از اینکه کاربر کلمه کلیدی را وارد کرد اجرا میشود |
onInputChanged | بعد از وارد کردن کلمه کلیدی هربار که کاربر تغییری در ورودی نوارد آدرس میدهد اجرا میشود. |
onInputEntered | کاربر ورودی خود را تایید میکند. مثلا بعد از وارد کردن، کلید enter را میفشارد |
onInputCancelled | کاربر از وارد کردن ورودی منصرف شده است؛ مثلا کلید ESC را فشرده است. |
chrome.omnibox.onInputEntered.addListener(function (text) { var location=""; switch(text) { case ".net tips Posts": location="https://www.dntips.ir/postsarchive"; break; case ".net tips News": location="https://www.dntips.ir/newsarchive"; break; case ".net tips Post Comments": location="https://www.dntips.ir/commentsarchive"; break; case".net tips News Comments": location="https://www.dntips.ir/newsarchive/comments"; break; default: location="https://www.dntips.ir/"; } chrome.tabs.getSelected(null, function (tab) { chrome.tabs.update(tab.id, { url: location }); }); });
var root = chrome.contextMenus.create({ title: 'Open .net tips', contexts: ['page'] }, function () { var Home= chrome.contextMenus.create({ title: 'Home', contexts: ['page'], parentId: root, onclick: function (evt) { chrome.tabs.create({ url: 'https://www.dntips.ir' }) } }); var Posts = chrome.contextMenus.create({ title: 'Posts', contexts: ['page'], parentId: root, onclick: function (evt) { chrome.tabs.create({ url: 'https://www.dntips.ir/postsarchive/' }) } }); });
public class EntityConfigurations { internal static void LoadEntityConfigurations(Assembly[] asm, DbModelBuilder modelBuilder) { if (asm == null) throw new ArgumentNullException(nameof(asm)); foreach (var configurations in asm.Select(assembly => assembly.GetTypes() .Where( type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)) .ToList())) { configurations.ForEach(type => { dynamic instance = Activator.CreateInstance(type); modelBuilder.Configurations.Add(instance); }); } } }
نحوه فراخوانی:
/// <summary> /// /// </summary> /// <param name="modelBuilder"></param> protected override void OnModelCreating(DbModelBuilder modelBuilder) { EntityConfigurations.LoadEntityConfigurations(AppDomain.CurrentDomain.GetAssemblies(), modelBuilder); }
منابع اصلی Ember.js
پیش از شروع به بحث نیاز است با تعدادی از سایتهای اصلی مرتبط با Ember.js آشنا شد:
سایت اصلی: http://emberjs.com
مخزن کدهای آن: https://github.com/emberjs
انجمن اختصاصی پرسش و پاسخ: http://discuss.emberjs.com
موتور قالبهای آن: http://handlebarsjs.com
لیست منابع مطالعاتی مرتبط مانند ویدیوهای آموزشی و لیست مقالات موجود: http://emberwatch.com
و بستهی نیوگت آن: https://www.nuget.org/packages/EmberJS
مفاهیم پایهای Ember.js
شیء Application
App = Ember.Application.create();
مسیر یابی
با مرور قسمتهای مختلف برنامه توسط کاربر، نیاز است حالات برنامه را مدیریت کرد؛ اینجا است که کار قسمت مسیریابی شروع میشود. مسیریابی، منابع مورد نیاز جهت آدرسهای مشخصی را تامین میکند.
App.Router.map(function() { this.resource('accounts'); // takes us to /accounts this.resource('gallery'); // takes us to /gallery });
به این ترتیب مسیرهای accounts/ و gallery/ قابل پردازش خواهند شد.
این مسیرها، تو در تو نیز میتوانند باشند. برای مثال:
App.Router.map(function() { this.resource('news', function() { this.resource('images', function () { // takes us to /news/images this.route('add');// takes us to /news/images/add }); }); });
مدلها
مدلها همان اشیایی هستند که برنامه مورد استفاده قرار میدهد و میتوانند یک آرایهی ساده و یا اشیاء JSON دریافتی از وب سرور باشند.
حداقل به دو روش میتوان مدلها را تعریف کرد:
الف) با استفاده از افزونهی Ember Data
ب) با کمک شیء Ember.Object
App.SiteLink = Ember.Object.extend({}); App.SiteLink.reopenClass({ findAll: function() { var links = []; //… $.getJSON … return links; } });
در ادامه متد دلخواهی را ایجاد کرده و برای مثال آرایهای از اشیاء دلخواه جاوا اسکریپتی را بازگشت خواهیم داد.
پس از تعریف مدل، نیاز است آنرا به سیستم مسیریابی معرفی کرد:
App.GalleryRoute = Ember.Route.extend({ model: function() { return App.SiteLink.findAll(); } });
کنترلرها
کنترلرها جهت ارائهی اطلاعات مدلها به View و قالب برنامه تعریف میشوند. در اینجا همیشه باید بخاطر داشت که model تامین کنندهی اطلاعات است. کنترلر جهت در معرض دید قرار دادن این اطلاعات، به View برنامه کاربرد دارد و مدلها هیچ اطلاعی از وجود کنترلرها ندارند.
کنترلرها علاوه بر اطلاعات model، میتوانند حاوی یک سری خواص و اشیاء صرفا نمایشی که قرار نیست در بانک اطلاعاتی ذخیره شوند نیز باشند.
در Ember.js قالبها (templates) اطلاعات خود را از کنترلر دریافت میکنند. کنترلرها اطلاعات مدل را به همراه سایر خواص نمایشی مورد نیاز در اختیار View و قالبهای برنامه قرار میدهند.
برای تعریف یک کنترلر میتوان درون شیء مسیریابی، با تعریف متد setupController شروع کرد:
App.GalleryRoute = Ember.Route.extend({ setupController: function(controller) { controller.set('content', ['red', 'yellow', 'blue']); } });
روش دوم تعریف کنترلرها با ایجاد یک زیر کلاس از شیء Ember.Controller انجام میشود:
App.GalleryController = Ember.Controller.extend({ search: '', content: ['red', 'yellow', 'blue'], query: function() { var data = this.get('search'); this.transitionToRoute('search', { query: data }); } });
قالبها یا templates
قالبها قسمتهای اصلی رابط کاربری را تشکیل خواهند داد. در اینجا از کتابخانهای به نام handlebars برای تهیه قالبهای سمت کاربر کمک گرفته میشود.
<script type="text/x-handlebars" data-template-name="sayhello"> Hello, <strong>{{firstName}} {{lastName}}</strong>! </script>
<script type="text/x-handlebars" data-template-name="sayhello"> Hello, <strong>{{firstName}} {{lastName}}</strong>! {{#if person}} Welcome back, <strong>{{person.firstName}} {{person.lastName}}</strong>! {{/if}} <ul> {{#each friend in friends}} <li> {{friend.name}} </li> {{/each}} </ul> <img {{bindAttr src="link.url" }} /> {{#linkTo ''about}}About{{/linkTo}} </script>
بهترین مرجع آشنایی با ریز جزئیات کتابخانهی handlebars، مراجعه به سایت اصلی آن است.
قواعد پیش فرض نامگذاری در Ember.js
اگر به مثالهای فوق دقت کرده باشید، خواصی مانند GalleryController و یا GalleryRoute به شیء App اضافه شدهاند. این نوع نامگذاریها در ember.js بر اساس روش convention over configuration کار میکنند. برای نمونه اگر مسیریابی خاصی را به نحو ذیل تعریف کردید:
this.resource('employees');
کنترلر آن App.EmployeesController
مدل آن App.Employee
View آن App.EmployeesView
و قالب آن employees
بهتر است تعریف شوند. به عبارتی اگر اینگونه تعریف شوند، به صورت خودکار توسط Ember.js یافت شده و هر کدام با مسئولیتهای خاص مرتبط با آنها پردازش میشوند و همچنین ارتباطات بین آنها به صورت خودکار برقرار خواهد شد. به این ترتیب برنامه نظم بهتری خواهد یافت. با یک نگاه میتوان قسمتهای مختلف را تشخیص داد و همچنین کدنویسی پردازش و اتصال قسمتهای مختلف برنامه نیز به شدت کاهش مییابد.
تهیهی اولین برنامهی Ember.js
تا اینجا نگاهی مقدماتی داشتیم به اجزای تشکیل دهندهی هستهی Ember.js. در ادامه مثال سادهای را جهت نمایش ساختار ابتدایی یک برنامهی Ember.js، بررسی خواهیم کرد.
بستهی Ember.js را همانطور که در قسمت منابع اصلی آن در ابتدای بحث عنوان شد، میتوانید از سایت و یا مخزن کد آن دریافت کنید و یا اگر از VS.NET استفاده میکنید، تنها کافی است دستور ذیل را صادر نمائید:
PM> Install-Package EmberJS
در این حالت ترتیب تعریف اسکریپتهای مورد نیاز صفحه به صورت ذیل خواهند بود:
<script src="Scripts/jquery-2.1.1.js" type="text/javascript"></script> <script src="Scripts/handlebars.js" type="text/javascript"></script> <script src="Scripts/ember.js" type="text/javascript"></script> <script src="Scripts/app.js" type="text/javascript"></script>
App = Ember.Application.create(); App.IndexRoute = Ember.Route.extend({ setupController:function(controller) { controller.set('content', ['red', 'yellow', 'blue']); } });
App.Router.map(function() { this.resource('application'); this.resource('index'); });
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script src="Scripts/jquery-2.1.1.js" type="text/javascript"></script> <script src="Scripts/handlebars.js" type="text/javascript"></script> <script src="Scripts/ember.js" type="text/javascript"></script> <script src="Scripts/app.js" type="text/javascript"></script> </head> <body> <script type="text/x-handlebars" data-template-name="index"> Hello, <strong>Welcome to Ember.js</strong>! <ul> {{#each item in content}} <li> {{item}} </li> {{/each}} </ul> </script> </body> </html>
مقدار data-template-name در اینجا مهم است. اگر آنرا به هر نام دیگری بجز index تنظیم کنید، منبع دریافت اطلاعات آن مشخص نخواهد بود. نام index در اینجا به معنای اتصال این قالب به اطلاعات ارائه شده توسط کنترلر index است.
تا همینجا اگر برنامه را اجرا کنید، به خوبی کار خواهد کرد. نکتهی دیگری که در مورد قالبهای Ember.js قابل توجه هستند، قالب پیش فرض application است. با تعریف Ember.Application.create یک چنین قالبی نیز به ابتدای هر صفحه به صورت خودکار اضافه خواهد شد:
<body> <script type="text/x-handlebars" data-template-name="application"> <h1>Header</h1> {{outlet}} </script>
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید:
EmberJS01.zip
واکشی اولیه در HTML5 Prefetching - HTML5
[ApiController] [AllowAnonymous] [Route(template: "/.well-known")] public class PrefetchProxyController : ControllerBase { [HttpGet(template: "traffic-advice")] [Produces(contentType: "application/trafficadvice+json")] public IActionResult TrafficAdvice() => Ok(new[] { new PrefetchProxyTrafficAdvice() }); } public class PrefetchProxyTrafficAdvice { [JsonPropertyName(name: "user_agent")] public string UserAgent { set; get; } = "prefetch-proxy"; public bool Disallow { set; get; } = true; }
[ {"user_agent": "prefetch-proxy", "disallow": true} ]
Get-Help Get-Command
Get-Help Get-Command -Online
Get-Command -Name '*Process'
CommandType Name Version Sour ce ----------- ---- ------- ---- Cmdlet Debug-Process 7.0.0.0 Mic… Cmdlet Enter-PSHostProcess 7.2.6.500 Mic… Cmdlet Exit-PSHostProcess 7.2.6.500 Mic… Cmdlet Get-Process 7.0.0.0 Mic… Cmdlet Start-Process 7.0.0.0 Mic… Cmdlet Stop-Process 7.0.0.0 Mic… Cmdlet Wait-Process 7.0.0.0 Mic… Application mysqltest_safe_process 0.0.0.0
ls -l | grep "\.pdf$"
Get-Command -Name '*Process' | Select-Object Name,CommandType
Get-Command -Name '*Process' | Select-Object Name,CommandType | Sort-Object Name -Descending
PS /> Get-Command -Name '*Process' | Select-Object Name,CommandType -First 3 | Sort-Object Name -Descending Name CommandType ---- ----------- Exit-PSHostProcess Cmdlet Enter-PSHostProcess Cmdlet Debug-Process Cmdlet
PS /> Get-Process | Where-Object CPU -gt 1.24 | Sort-Object WorkingSet -Descending | Select-Object -First 5
- ByValue
- ByPropertyName
Get-Process Slack | Stop-Process
Get-Process | Get-Member
TypeName: System.Diagnostics.Process
PS /Users/sirwanafifi> Get-Help Stop-Process -Full NAME Stop-Process SYNTAX Stop-Process [-Id] <int[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>] Stop-Process -Name <string[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>] Stop-Process [-InputObject] <Process[]> [-PassThru] [-Force] [-WhatIf] [-Confirm] [<CommonParameters>] PARAMETERS -Confirm Required? false Position? Named Accept pipeline input? false Parameter set name (All) Aliases cf Dynamic? false Accept wildcard characters? false -Force Required? false Position? Named Accept pipeline input? false Parameter set name (All) Aliases None Dynamic? false Accept wildcard characters? false -Id <int[]> Required? true Position? 0 Accept pipeline input? true (ByPropertyName) Parameter set name Id Aliases None Dynamic? false Accept wildcard characters? false -InputObject <Process[]> Required? true Position? 0 Accept pipeline input? true (ByValue) Parameter set name InputObject Aliases None Dynamic? false Accept wildcard characters? false -Name <string[]> Required? true Position? Named Accept pipeline input? true (ByPropertyName) Parameter set name Name Aliases ProcessName Dynamic? false Accept wildcard characters? false -PassThru Required? false Position? Named Accept pipeline input? false Parameter set name (All) Aliases None Dynamic? false Accept wildcard characters? false -WhatIf Required? false Position? Named Accept pipeline input? false Parameter set name (All) Aliases wi Dynamic? false Accept wildcard characters? false <CommonParameters> This cmdlet supports the common parameters: Verbose, Debug, ErrorAction, ErrorVariable, WarningAction, WarningVariable, OutBuffer, PipelineVariable, and OutVariable. For more information, see about_CommonParameters (https://go.microsoft.com/fwlink/?LinkID=113216). INPUTS System.Int32[] System.String[] System.Diagnostics.Process[] OUTPUTS System.Diagnostics.Process ALIASES spps REMARKS Get-Help cannot find the Help files for this cmdlet on this computer. It is displaying only partial help. -- To download and install Help files for the module that includes this cmdlet, use Update-Help. -- To view the Help topic for this cmdlet online, type: "Get-Help Stop-Process -Online" or go to https://go.microsoft.com/fwlink/?LinkID=2097058.
-Id <int[]> Required? true Position? 0 Accept pipeline input? true (ByPropertyName) Parameter set name Id Aliases None Dynamic? false Accept wildcard characters? false -InputObject <Process[]> Required? true Position? 0 Accept pipeline input? true (ByValue) Parameter set name InputObject Aliases None Dynamic? false Accept wildcard characters? false -Name <string[]> Required? true Position? Named Accept pipeline input? true (ByPropertyName) Parameter set name Name Aliases ProcessName Dynamic? false Accept wildcard characters? false
"Slack" | Stop-Process
Stop-Process: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
PS /Users/sirwanafifi> $newObject = [pscustomobject]@{ Name = "Slack" } PS /Users/sirwanafifi> $newObject | Stop-Process
{ "name": "dntwebpack", "version": "1.0.0", "description": "a webpack tutorial", "main": "main.js", "scripts": { }, "author": "mehdi", "license": "MIT" }
<html> <!-- index.html --> <head> first part of webpack tut! </head> <body> <h1>webpack is awesome !</h1> <script src="bundle.js"></script> </body> </html>
//main.js //start of the journey with webpack console.log(`i'm bundled by webpack`);
فایل bundle.js را تولید میکنیم.
{ "name": "dntwebpack", "version": "1.0.0", "description": "", "main": "main.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" ,"webpack":"webpack" }, "author": "mehdi", "license": "ISC", "devDependencies": { "webpack": "^1.13.1" } }
CoffeeScript #2
Syntax
برای کار با CoffeeScript، ابتدا باید با ساختار Syntax آن آشنا شد. CoffeeScript در بسیاری از موارد با جاوااسکریپت یکسان است در حالیکه در قسمت قبل گفته شد که CoffeeScript زیر مجموعهای جاوااسکریپت نیست؛ بنابراین برخی از کلمات کلیدی مانند function و var در آن مجاز نیست و سبب بروز خطا در زمان کامپایل میشوند. وقتی شما شروع به نوشتن فایل CoffeeScript میکنید، باید تمام کدهایی را که مینویسید، با Syntax کامل CoffeeScript بنویسید و نمیتوانید قسمتی را با جاوااسکریپت و قسمتی را با CoffeeScript بنویسید.
برای نوشتن توضیحات در فایل CoffeeScript باید از علامت # استفاده کنید که این قسمت را از زبان Ruby گرفته است.
# A comment
### A multiline comment ###
در زبان CoffeeScript فاصله (space) بسیار مهم است؛ چرا که زبان Python براساس میزان تو رفتگی کدها، بدنهی شرطها و حلقهها را تشخیص میدهد و CoffeeScript نیز از این ویژگی استفاده میکند. هرگاه بخواهید از {} استفاده کنید فقط کافی است از کلید Tab استفاده کنید تا پس از کامپایل به صورت {} تبدیل شود.
Variables & Scope
CoffeeScript یکی از باگهایی را که در نوشتن جاوااسکریپت وجود دارد (متغیرهای سراسری) حل کرده است. در جاوااسکریپت درصورتیکه هنگام تعریف متغیری از کلمهی کلیدی var در پشت اسم متغیر استفاده نشود، به صورت سراسری تعریف میشود. CoffeeScript به سادگی متغیرهای سراسری را حذف میکند. در پشت صحنهی این حذف، اسکریپت نوشته شده را درون یک تابع بدون نام قرار میدهد و با این کار تمامی متغیرها در ناحیهی محلی قرار میگیرند و سپس قبل از نام هر متغیری، کلمهی کلیدی var را قرار میدهد. برای مثال:
myVariable = "vahid"
var myVariable; myVariable = "vahid";
با این حال گاهی اوقات نیاز است که متغیر سراسری تعریف کنید. برای اینکار باید از شیء سراسری موجود در مرورگر (window) یا از روش زیر استفاده کنید:
exports = this exports.MyVariable = "vahid"
Functions
CoffeeScript برای راحتی در نوشتن توابع، کلمه کلیدی function را حذف کرده و به جای آن از <- استفاده میکند. توابع در CoffeeScript میتوانند در یک خط یا به صورت تورفته در چندین خط نوشته شده باشند. آخرین عبارتی که در یک تابع نوشته میشود به صورت ضمنی بازگشت داده میشود. در صورتیکه نیاز به بازگرداندن مقداری در تابع ندارید، از کلمهی return به تنهایی استفاده کنید.
func = -> "vahid"
var func; func = function() { return "vahid"; };
func = -> # An extra line "vahid"
Function arguments
برای تعریف آرگومان در توابع باید قبل از <- از () استفاده کرد و آرگومان هایی را که نیاز است، در داخل آن تعریف کرد. برای مثال:
func = (a, b) -> a * b
var func; func = function(a, b) { return a * b; };
func = (a = 1, b = 2) -> a * b
sum = (nums...) -> result = 0 nums.forEach (n) -> result += n result
var sum, slice = [].slice; sum = function() { var nums, result; nums = 1 <= arguments.length ? slice.call(arguments, 0) : []; result = 0; nums.forEach(function(n) { return result += n; }); return result; };
فراخوانی توابع
برای فراخوانی توابع میتوانید به مانند جاوااسکریپت از با پرانتز () یا ()apply و یا ()call صدا زده شوند. اگرچه مانند Ruby، کامپایلر CoffeeScript میتوانند به صورت اتوماتیک توابعی با حداقل یک آرگومان را فراخوانی کند.
a = "Vahid!" alert a # برابر است با alert(a) alert inspect a # برابر است با alert(inspect(a))
در صورتی که تابعی بدون آرگومان باشد، برای فراخوانی آن بدون نوشتن پرانتز بعد از نام تابع، CoffeeScript نمیتواند تشخیص دهند که این یک تابع است و مانند یک متغیر با آن برخورد میکند. دراین رابطه، رفتار CoffeeScript بسیار شبیه به Python میباشد.