日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

k8s angular mysql_Angular 实践:如何优雅地发起和处理请求

發(fā)布時間:2024/9/19 数据库 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 k8s angular mysql_Angular 实践:如何优雅地发起和处理请求 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Tips: 本文實現(xiàn)重度依賴 ObservableInput,靈感來自靈雀云同事實現(xiàn)的 asyncData 指令,但之前沒有 ObservableInput 的裝飾器,處理響應(yīng) Input 變更相對麻煩一些,所以這里使用 ObservableInput 重新實現(xiàn)。

What And Why

大部分情況下處理請求有如下幾個過程:

看著很復(fù)雜的樣子,既要 Loading,又要 Reload,還要 Retry,如果用命令式寫法可能會很蛋疼,要處理各種分支,而今天要講的 rxAsync 指令就是用來優(yōu)雅地解決這個問題的。

How

我們來思考下如果解決這個問題,至少有如下四個點需要考慮。

1.發(fā)起請求有如下三種情況:

第一次渲染主動加載

用戶點擊重新加載

加載出錯自動重試

2.渲染的過程中需要根據(jù)請求的三種狀態(tài) ——?loading,?success,?error?(類似?Promise?的?pending,?resolved,?rejected) —— 動態(tài)渲染不同的內(nèi)容

3.輸入的參數(shù)發(fā)生變化時我們需要根據(jù)最新參數(shù)重新發(fā)起請求,但是當(dāng)用戶輸入的重試次數(shù)變化時應(yīng)該忽略,因為重試次數(shù)只影響?Error?狀態(tài)

4.用戶點擊重新加載可能在我們的指令內(nèi)部,也可能在指令外部

Show Me the Code

話不多說,上代碼:

@Directive({

selector: '[rxAsync]',

})

export class AsyncDirective

implements OnInit, OnDestroy {

@ObservableInput()

@Input('rxAsyncContext')

private context$!: Observable // 自定義 fetcher 調(diào)用時的 this 上下文,還可以通過箭頭函數(shù)、fetcher.bind(this) 等方式解決

@ObservableInput()

@Input('rxAsyncFetcher')

private fetcher$!: Observable>> // 自動發(fā)起請求的回調(diào)函數(shù),參數(shù)是下面的 params,應(yīng)該返回 Observable

@ObservableInput()

@Input('rxAsyncParams')

private params$!: Observable

// fetcher 調(diào)用時傳入的參數(shù)

@Input('rxAsyncRefetch')

private refetch$$ = new Subject() // 支持用戶在指令外部重新發(fā)起請求,用戶可能不需要,所以設(shè)置一個默認(rèn)值

@ObservableInput()

@Input('rxAsyncRetryTimes')

private retryTimes$!: Observable // 發(fā)送 Error 時自動重試的次數(shù),默認(rèn)不重試

private destroy$$ = new Subject()

private reload$$ = new Subject()

private context = {

reload: this.reload.bind(this), // 將 reload 綁定到 template 上下文中,方便用戶在指令內(nèi)重新發(fā)起請求

} as IAsyncDirectiveContext

private viewRef: Nullable

private sub: Nullable

constructor(

private templateRef: TemplateRef,

private viewContainerRef: ViewContainerRef,

) {}

reload() {

this.reload$$.next()

}

ngOnInit() {

// 得益于 ObservableInput ,我們可以一次性響應(yīng)所有參數(shù)的變化

combineLatest([

this.context$,

this.fetcher$,

this.params$,

this.refetch$$.pipe(startWith(null)), // 需要 startWith(null) 觸發(fā)第一次請求

this.reload$$.pipe(startWith(null)), // 同上

])

.pipe(

takeUntil(this.destroy$$),

withLatestFrom(this.retryTimes$), // 忽略 retryTimes 的變更,我們只需要取得它的最新值即可

)

.subscribe(([[context, fetcher, params], retryTimes]) => {

// 如果參數(shù)變化且上次請求還沒有完成時,自動取消請求忽略掉

this.disposeSub()

// 每次發(fā)起請求前都重置 loading 和 error 的狀態(tài)

Object.assign(this.context, {

loading: true,

error: null,

})

this.sub = fetcher

.call(context, params)

.pipe(

retry(retryTimes), // 錯誤時重試

finalize(() => {

// 無論是成功還是失敗,都取消 loading,并重新觸發(fā)渲染

this.context.loading = false

if (this.viewRef) {

this.viewRef.detectChanges()

}

}),

)

.subscribe(

data => (this.context.$implicit = data),

error => (this.context.error = error),

)

if (this.viewRef) {

return this.viewRef.markForCheck()

}

this.viewRef = this.viewContainerRef.createEmbeddedView(

this.templateRef,

this.context,

)

})

}

ngOnDestroy() {

this.disposeSub()

this.destroy$$.next()

this.destroy$$.complete()

if (this.viewRef) {

this.viewRef.destroy()

this.viewRef = null

}

}

disposeSub() {

if (this.sub) {

this.sub.unsubscribe()

this.sub = null

}

}

}

Usage

總共 100 多行的源碼,說是很優(yōu)雅,那到底使用的時候優(yōu)不優(yōu)雅呢?來個實例看看:

@Component({

selector: 'rx-async-directive-demo',

template: `

Refetch (Outside rxAsync)

*rxAsync="

let todo;

let loading = loading;

let error = error;

let reload = reload;

context: context;

fetcher: fetchTodo;

params: todoId;

refetch: refetch$$;

retryTimes: retryTimes

"

>

Reload

loading: {{ loading }} error: {{ error | json }}

todo: {{ todo | json }}

`,

preserveWhitespaces: false,

changeDetection: ChangeDetectionStrategy.OnPush,

})

class AsyncDirectiveComponent {

context = this

@Input()

todoId = 1

@Input()

retryTimes = 0

refetch$$ = new Subject()

constructor(private http: HttpClient) {}

fetchTodo(todoId: string) {

return typeof todoId === 'number'

? this.http.get('//jsonplaceholder.typicode.com/todos/' + todoId)

: EMPTY

}

}

總結(jié)

以上是生活随笔為你收集整理的k8s angular mysql_Angular 实践:如何优雅地发起和处理请求的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。