<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                &emsp;&emsp;在[上一篇](https://www.cnblogs.com/strick/p/16178207.html)中,主要分析了package.json和application.js文件,本文會分析剩下的幾個文件。 ## 一、context.js &emsp;&emsp;在context.js中,會處理錯誤,cookie,JSON格式化等。 **1)cookie** &emsp;&emsp;在處理cookie時,創建了一個Symbol類型的key,注意[Symbol](http://www.hmoore.net/pwstrick/fe-questions/1094977)具有唯一性的特點,即?Symbol('context#cookies') ===?Symbol('context#cookies') 得到的是 false。 ~~~ const Cookies = require('cookies') const COOKIES = Symbol('context#cookies') const proto = module.exports = { get cookies () { if (!this[COOKIES]) { this[COOKIES] = new Cookies(this.req, this.res, { keys: this.app.keys, secure: this.request.secure }) } return this[COOKIES] }, set cookies (_cookies) { this[COOKIES] = _cookies } } ~~~ &emsp;&emsp;get在讀取cookie,會初始化Cookies實例。 **2)錯誤** &emsp;&emsp;在默認的錯誤處理函數中,會配置頭信息,觸發錯誤事件,配置響應碼等。 ~~~ onerror (err) { // 可以繞過KOA的錯誤處理 if (err == null) return // 在處理跨全局變量時,正常的“instanceof”檢查無法正常工作 // See https://github.com/koajs/koa/issues/1466 // 一旦jest修復,可能會刪除它 https://github.com/facebook/jest/issues/2549. const isNativeError = Object.prototype.toString.call(err) === '[object Error]' || err instanceof Error if (!isNativeError) err = new Error(util.format('non-error thrown: %j', err)) let headerSent = false if (this.headerSent || !this.writable) { headerSent = err.headerSent = true } // 觸發error事件,在application.js中創建過監聽器 this.app.emit('error', err, this) // nothing we can do here other // than delegate to the app-level // handler and log. if (headerSent) { return } const { res } = this // 首先取消設置所有header /* istanbul ignore else */ if (typeof res.getHeaderNames === 'function') { res.getHeaderNames().forEach(name => res.removeHeader(name)) } else { res._headers = {} // Node < 7.7 } // 然后設置那些指定的 this.set(err.headers) // 強制 text/plain this.type = 'text' let statusCode = err.status || err.statusCode // ENOENT support if (err.code === 'ENOENT') statusCode = 404 // default to 500 if (typeof statusCode !== 'number' || !statuses[statusCode]) statusCode = 500 // 響應數據 const code = statuses[statusCode] const msg = err.expose ? err.message : code this.status = err.status = statusCode this.length = Buffer.byteLength(msg) res.end(msg) }, ~~~ **3)屬性委托** &emsp;&emsp;在package.json中依賴了一個名為delegates的庫,看下面這個示例。 &emsp;&emsp;request是context的一個屬性,在調delegate(context, 'request')函數后,就能直接context.querystring這么調用了。 ~~~ const delegate = require('delegates') const context = { request: { querystring: 'a=1&b=2' } } delegate(context, 'request') .access('querystring') console.log(context.querystring)// a=1&b=2 ~~~ &emsp;&emsp;在KOA中,ctx可以直接調用request與response的屬性和方法就是通過delegates實現的。 ~~~ delegate(proto, 'request') .method('acceptsLanguages') .method('acceptsEncodings') .method('acceptsCharsets') .method('accepts') .method('get') .method('is') .access('querystring') .access('idempotent') .access('socket') .access('search') .access('method') ... ~~~ ## 二、request.js和response.js &emsp;&emsp;request.js和response.js就是為Node原生的req和res做一層封裝。在request.js中都是些HTTP首部、IP、URL、緩存等。 ~~~ /** * 獲取 WHATWG 解析的 URL,并緩存起來 */ get URL () { /* istanbul ignore else */ if (!this.memoizedURL) { const originalUrl = this.originalUrl || '' // avoid undefined in template string try { this.memoizedURL = new URL(`${this.origin}${originalUrl}`) } catch (err) { this.memoizedURL = Object.create(null) } } return this.memoizedURL }, /** * 檢查請求是否新鮮(有緩存),也就是 * If-Modified-Since/Last-Modified 和 If-None-Match/ETag 是否仍然匹配 */ get fresh () { const method = this.method const s = this.ctx.status // GET or HEAD for weak freshness validation only if (method !== 'GET' && method !== 'HEAD') return false // 2xx or 304 as per rfc2616 14.26 if ((s >= 200 && s < 300) || s === 304) { return fresh(this.header, this.response.header) } return false }, ~~~ &emsp;&emsp;response.js要復雜一點,會配置狀態碼、響應正文、讀取解析的響應內容長度、302重定向等。 ~~~ /** * 302 重定向 * Examples: * this.redirect('back'); * this.redirect('back', '/index.html'); * this.redirect('/login'); * this.redirect('http://google.com'); */ redirect (url, alt) { // location if (url === 'back') url = this.ctx.get('Referrer') || alt || '/' this.set('Location', encodeUrl(url)) // status if (!statuses.redirect[this.status]) this.status = 302 // html if (this.ctx.accepts('html')) { url = escape(url) this.type = 'text/html; charset=utf-8' this.body = `Redirecting to <a href="${url}">${url}</a>.` return } // text this.type = 'text/plain; charset=utf-8' this.body = `Redirecting to ${url}.` }, /** * 設置響應正文 */ set body (val) { const original = this._body this._body = val // no content if (val == null) { if (!statuses.empty[this.status]) { if (this.type === 'application/json') { this._body = 'null' return } this.status = 204 } if (val === null) this._explicitNullBody = true this.remove('Content-Type') this.remove('Content-Length') this.remove('Transfer-Encoding') return } // set the status if (!this._explicitStatus) this.status = 200 // set the content-type only if not yet set const setType = !this.has('Content-Type') // string if (typeof val === 'string') { if (setType) this.type = /^\s*</.test(val) ? 'html' : 'text' this.length = Buffer.byteLength(val) return } // buffer if (Buffer.isBuffer(val)) { if (setType) this.type = 'bin' this.length = val.length return } // stream if (val instanceof Stream) { onFinish(this.res, destroy.bind(null, val)) if (original !== val) { val.once('error', err => this.ctx.onerror(err)) // overwriting if (original != null) this.remove('Content-Length') } if (setType) this.type = 'bin' return } // json this.remove('Content-Length') this.type = 'json' }, ~~~ ## 三、單元測試 &emsp;&emsp;KOA的單元測試做的很細致,每個方法和屬性都給出了相應的單測,它內部的寫法很容易單測,非常值得借鑒。 &emsp;&emsp;采用的單元測試框架是[Jest](https://jestjs.io/),HTTP請求的測試庫是[SuperTest](https://github.com/visionmedia/supertest)。斷言使用了Node默認提供的[assert](https://nodejs.org/dist/latest-v18.x/docs/api/assert.html)模塊。 ~~~ const request = require('supertest') const assert = require('assert') const Koa = require('../..') // request.js describe('app.request', () => { const app1 = new Koa() // 聲明request的message屬性 app1.request.message = 'hello' it('should merge properties', () => { app1.use((ctx, next) => { // 判斷ctx中的request.message是否就是剛剛賦的那個值 assert.strictEqual(ctx.request.message, 'hello') ctx.status = 204 }) // 發起GET請求,地址是首頁,期待響應碼是204 return request(app1.listen()) .get('/') .expect(204) }) }) ~~~ ***** > 原文出處: [博客園-Node.js躬行記](https://www.cnblogs.com/strick/category/1688575.html) [知乎專欄-Node.js躬行記](https://zhuanlan.zhihu.com/pwnode) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎閱讀。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看