以 iOS 而言,你可能要透過 NSOperationQueue 或者 GCD (Grand Central Dispatch) 這些方法來做非同步的流程。
如果要接續觸發( A 事情做完做 B )的情境,A 事情的 callback 做完之後緊接著 B 事情,你可能會得到一個很深的縮排。
如果是互相等待完成( A 跟 B 事情 )的情境,你可能要透過一些 boolean 來把狀態記住,然後 A 事情跟 B 事情的 callback 同時要檢查對方是否做完,才接續另外一個 callback 。 以上並不是說這樣寫不能用,只是你會有更好的解法,讓程式碼變得更乾淨好閱讀。
firstly {
// Show Loading status bar
return when(myAsnycTaskA(), myAsnycTaskB())
}.then { (resultA:MyObjectA, resultB:MyObjectB) -> Void in
// Show results
}.always {
// Hide Loading status bar
}.catch { error in
print(error)
}
最簡單的範例
這是一個最基本的範例
基本句型有 then 跟 catch 就可以了
myAsnycTaskA().then {
(resultA:MyObjectA) -> Void in
// Show results
}.catch { error in
print(error)
}
firstly {
// Show Loading status bar
return when(myAsnycTaskA(), myAsnycTaskB())
}.then { (resultA:MyObjectA, resultB:MyObjectB) -> Promise<MyObjectC> in
// So some processing
return myProcessingTaskC()
}.then { (resultC:MyObjectC) -> Void in
// Show results
}.always {
// Hide Loading status bar
}.catch { error in
print(error)
}
#
# Default PF configuration file.
#
# This file contains the main ruleset, which gets automatically loaded
# at startup. PF will not be automatically enabled, however. Instead,
# each component which utilizes PF is responsible for enabling and disabling
# PF via -E and -X as documented in pfctl(8). That will ensure that PF
# is disabled only when the last enable reference is released.
#
# Care must be taken to ensure that the main ruleset does not get flushed,
# as the nested anchors rely on the anchor point defined here. In addition,
# to the anchors loaded by this file, some system services would dynamically
# insert anchors into the main ruleset. These anchors will be added only when
# the system service is used and would removed on termination of the service.
#
# See pf.conf(5) for syntax.
#
#
# com.apple anchor point
#
scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"
# 最佳化模式:一般模式
set optimization normal
# 阻擋的策略:直接丟棄
set block-policy drop
# 封包需要照順序
set require-order yes
# 跳過 lookback 介面不處理
set skip on lo
# log 紀錄只記最危急的等級
set debug urgent
# === Developer machine example ===
# 指定連線介面
int_if="{ en0 en1 }"
# 指定要開放 連入 的服務
webports = "{http, https}"
# 定義私有IP範圍
table <private> const { 192.168/16 }
# 預設允許所有連出連入連線,並保持狀態
pass in all keep state
pass out all keep state
# 跳過 lookback 介面不處理
set skip on lo
# MySQL (TCP:3306) 允許本機 lookback 介面 能連線,阻擋其他的封包
pass in quick on lo proto tcp from any to any port 3306
block in quick proto tcp from any to any port 3306
# 只允許私有 IP 能連線,阻擋其他的封包
pass in quick proto tcp from <private> to any port webports
block in quick proto tcp from any to any port webports
測試
設定好了之後來測試,這裡列出幾個:
是否本機能正常連線到 MySQL?
找一台同網段的裝置,是否無法連接 MySQL?
找一台接不同網路的裝置來測試,是否無法連接 MySQL?
是否本機能正常看到自己開發中的網站?
找一台同網段的裝置,是否能正常看到網站?
找一台接不同網路的裝置來測試,是否能正常看到網站?
附註:MySQL 連線指令為
$ mysql -u root -h <YOUR_IP> -p
測試 HTTP 伺服器
$ docker run -d -p 80:00 j796160836/simple-test-http
使用 docker 這個測試 image,
對應內部 container 80 port (後者) 到主機 80 port (前者)
# === HTTP server example ====
# 指定對外連線介面
ext_if="{ ppp0 }"
# 指定要開放 連入 的服務
webports = "{http, https}"
# 指定要開放的 連出 的服務
int_tcp_services = "{domain, ssh, ntp, www, https}"
int_udp_services = "{domain, ntp}"
# 跳過 lookback 介面不處理
set skip on lo
# 重新組合封包
scrub in all random-id fragment reassemble
# 擋掉所有 進入 的連線
block drop in log all
# 擋掉所有 連出 的連線
block out all
# 阻擋惡意偽造封包
antispoof quick for $ext_if
# 指定要開放 連入 的服務
pass in on $ext_if proto tcp from any to any port $webports
# 指定要開放的 連出 的服務
pass out quick on $ext_if proto tcp to any port $int_tcp_services
pass out quick on $ext_if proto udp to any port $int_udp_services
# 接受 PING 回應
pass on $ext_if inet proto icmp to $ext_if icmp-type "echoreq" keep state
# 接受使用 traceroute
pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state
— OS X Continuity Activation Tool 2.0.0 — by dokterdok
— Initiating system compatibility check —
Verifying Mac model reference… OK Verifying Mac board-id… OK Verifying OS X version… OK Verifying Wi-Fi hardware… OK Verifying Bluetooth version… OK Verifying Bluetooth features… OK Verifying kexts readability… OK Verifying Bluetooth blacklist status… OK Verifying Wi-Fi whitelist status… OK Verifying legacy Wi-Fi card patch… OK Verifying old Wi-Fi kext presence… OK
— Initiating Continuity mod —
Disabling OS kext protection… OK Fixing disk permissions… OK Backing up original drivers… OK. Wi-Fi and Bluetooth kexts were backed up in ‘…’ Skipping blacklist patch… OK Patching whitelist……………. OK Cleaning up old Wi-Fi kext… OK Applying legacy Wi-Fi card patch… OK Verifying BT4 dongle patch status… OK Setting HCI switch behavior… OK Patching Bluetooth feature flags… OK Skipping legacy Wi-Fi cards patch… OK Applying correct permissions… OK Updating kext caches… OK Updating system caches… OK Backing up patched drivers… OK. Wi-Fi and Bluetooth kexts were backed up in ‘…’
ALMOST DONE! After rebooting: 1) Make sure that both your Mac and iOS device have Bluetooth turned on, and are on the same Wi-Fi network. 2) On OS X go to SYSTEM PREFERENCES> GENERAL> and ENABLE HANDOFF. 3) On iOS go to SETTINGS> GENERAL> HANDOFF & SUGGESTED APPS> and ENABLE HANDOFF. 4) On OS X, sign out and then sign in again to your iCloud account. Troubleshooting: support.apple.com/kb/TS5458
Thanks to Lem3ssie, UncleSchnitty, Skvo, toleda, TealShark, Manic Harmonic, rob3r7o and the many beta testers for their support.