more docs
This commit is contained in:
parent
d6e18ca134
commit
3a19dddb22
5 changed files with 113 additions and 24 deletions
|
|
@ -68,7 +68,9 @@ o.spec("mount", function() {
|
|||
}, FRAME_BUDGET)
|
||||
})
|
||||
|
||||
o("redraws several mount points on events", function(done) {
|
||||
o("redraws several mount points on events", function(done, timeout) {
|
||||
timeout(60)
|
||||
|
||||
var onupdate0 = o.spy()
|
||||
var oninit0 = o.spy()
|
||||
var onclick0 = o.spy()
|
||||
|
|
|
|||
71
docs/jsonp.md
Normal file
71
docs/jsonp.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# jsonp(options)
|
||||
|
||||
- [API](#api)
|
||||
- [How it works](#how-it-works)
|
||||
- [Typical usage](#typical-usage)
|
||||
|
||||
---
|
||||
|
||||
### API
|
||||
|
||||
`stream = m.jsonp(options)`
|
||||
|
||||
Argument | Type | Required | Description
|
||||
---------------------- | --------------------------------- | -------- | ---
|
||||
`options.url` | `String` | Yes | The URL to send the request to. The URL may be either absolute or relative, and it may contain [interpolations](#dynamic-urls).
|
||||
`options.data` | `any` | No | The data to be interpolated into the URL and serialized into the querystring (for GET requests) or body (for other types of requests).
|
||||
`options.type` | `any = Function(any)` | No | A constructor to be applied to each object in the response. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function).
|
||||
`options.initialValue` | `any` | No | A value to populate the returned stream before the request completes
|
||||
`options.callbackName` | `String` | No | The name of the function that will be called as the callback. Defaults to a randomized string (e.g. `_mithril_6888197422121285_0({a: 1})`
|
||||
`options.callbackKey` | `String` | No | The name of the querystring parameter name that specifies the callback name. Defaults to `callback` (e.g. `/someapi?callback=_mithril_6888197422121285_0`)
|
||||
**returns** | `Stream` | | A stream that resolves to the response data, after it has been piped through `type` method
|
||||
|
||||
[How to read signatures](signatures.md)
|
||||
|
||||
---
|
||||
|
||||
#### How it works
|
||||
|
||||
The `m.jsonp` utility is useful for third party APIs that can return data in [JSON-P](https://en.wikipedia.org/wiki/JSONP) format.
|
||||
|
||||
In a nutshell, JSON-P consists of creating a `script` tag whose `src` attribute points to a script that lives in the server outside of your control. Typically, you are required to define a global function and specify its name in the querystring of the script's URL. The response will return code that calls your global function, passing the server's data as the first parameter.
|
||||
|
||||
JSON-P has several limitations: it can only use GET requests, it implicitly trusts that the third party server won't serve malicious code and it requires polluting the global Javascript scope. Nonetheless, it is sometimes the only available way to retrieve data from a service (for example, if the service doesn't support [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)).
|
||||
|
||||
---
|
||||
|
||||
### Typical usage
|
||||
|
||||
Some services follow the de-facto convention of responding with JSON-P if a `callback` querystring key is provided, thus making `m.jsonp` automatically work without any effort:
|
||||
|
||||
```javascript
|
||||
m.jsonp({url: "https://api.github.com/users/lhorie"}).run(function(response) {
|
||||
console.log(response.data.login) // logs "lhorie"
|
||||
})
|
||||
```
|
||||
|
||||
Some services do not follow conventions and therefore you must specify the callback key that the service expects:
|
||||
|
||||
```javascript
|
||||
m.jsonp({
|
||||
url: "https://api.flickr.com/services/feeds/photos_public.gne?tags=kitten&format=json",
|
||||
callbackKey: "jsoncallback",
|
||||
})
|
||||
.run(function(response) {
|
||||
console.log(response.link) // logs "https://www.flickr.com/photos/tags/kitten/"
|
||||
})
|
||||
```
|
||||
|
||||
And sometimes, you just want to take advantage of HTTP caching for GET requests for rarely-modified data:
|
||||
|
||||
```javascript
|
||||
//this request is always called with the same querystring, and therefore it is cached
|
||||
m.jsonp({
|
||||
url: "https://api.github.com/users/lhorie"
|
||||
callbackName: "__callback"
|
||||
})
|
||||
.run(function(response) {
|
||||
console.log(response.data.login) // logs "lhorie"
|
||||
})
|
||||
```
|
||||
|
||||
|
|
@ -100,6 +100,14 @@ This browser behavior may seem surprising to a developer coming from jQuery, bec
|
|||
|
||||
As a general rule of thumb, you should avoid using `m.trust` unless you are explicitly rendering rich text and there's no other way to get the results that you want.
|
||||
|
||||
```javascript
|
||||
// AVOID
|
||||
m("div", m.trust("hello world"))
|
||||
|
||||
// PREFER
|
||||
m("div", "hello world")
|
||||
```
|
||||
|
||||
#### Avoid blind copying and pasting
|
||||
|
||||
One common way to misuse `m.trust` is when working with third party services whose tutorials include HTML code to be copied and pasted. In most cases, HTML should be written using vnodes (typically via the [`m()`](hyperscript.md) utility)
|
||||
|
|
@ -148,7 +156,7 @@ var FacebookLikeButton = {
|
|||
}
|
||||
```
|
||||
|
||||
The Mithril component above simply pulls out the script tag's exact content into the `oncreate` hook and declares the remaining HTML tags using Mithril's `m()` syntax.
|
||||
The Mithril component above simply copies the script tag's code into the `oncreate` hook and declares the remaining HTML tags using Mithril's `m()` syntax.
|
||||
|
||||
#### Avoid HTML entities
|
||||
|
||||
|
|
|
|||
26
mithril.js
26
mithril.js
|
|
@ -810,16 +810,7 @@ var requestService = function($window) {
|
|||
try {
|
||||
var response = args.deserialize(args.extract(xhr, args))
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
if (typeof args.type === "function") {
|
||||
if (response instanceof Array) {
|
||||
for (var i = 0; i < response.length; i++) {
|
||||
response[i] = new args.type(response[i])
|
||||
}
|
||||
}
|
||||
else response = new args.type(response)
|
||||
}
|
||||
|
||||
stream(response)
|
||||
stream(cast(args.type, response))
|
||||
}
|
||||
else {
|
||||
var error = new Error(xhr.responseText)
|
||||
|
|
@ -841,12 +832,13 @@ var requestService = function($window) {
|
|||
}
|
||||
function jsonp(args) {
|
||||
var stream = Stream.stream()
|
||||
if (args.initialValue !== undefined) stream(args.initialValue)
|
||||
|
||||
var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++
|
||||
var script = $window.document.createElement("script")
|
||||
$window[callbackName] = function(data) {
|
||||
script.parentNode.removeChild(script)
|
||||
stream(data)
|
||||
stream(cast(args.type, data))
|
||||
if (typeof oncompletion === "function") oncompletion()
|
||||
delete $window[callbackName]
|
||||
}
|
||||
|
|
@ -889,6 +881,18 @@ var requestService = function($window) {
|
|||
}
|
||||
function extract(xhr) {return xhr.responseText}
|
||||
|
||||
function cast(type, data) {
|
||||
if (typeof type === "function") {
|
||||
if (data instanceof Array) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
data[i] = new type(data[i])
|
||||
}
|
||||
}
|
||||
else return new type(data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
return {xhr: xhr, jsonp: jsonp, setCompletionCallback: setCompletionCallback}
|
||||
}(window)
|
||||
var redrawService = function() {
|
||||
|
|
|
|||
|
|
@ -40,16 +40,7 @@ module.exports = function($window) {
|
|||
try {
|
||||
var response = args.deserialize(args.extract(xhr, args))
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
if (typeof args.type === "function") {
|
||||
if (response instanceof Array) {
|
||||
for (var i = 0; i < response.length; i++) {
|
||||
response[i] = new args.type(response[i])
|
||||
}
|
||||
}
|
||||
else response = new args.type(response)
|
||||
}
|
||||
|
||||
stream(response)
|
||||
stream(cast(args.type, response))
|
||||
}
|
||||
else {
|
||||
var error = new Error(xhr.responseText)
|
||||
|
|
@ -72,12 +63,13 @@ module.exports = function($window) {
|
|||
|
||||
function jsonp(args) {
|
||||
var stream = Stream.stream()
|
||||
if (args.initialValue !== undefined) stream(args.initialValue)
|
||||
|
||||
var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++
|
||||
var script = $window.document.createElement("script")
|
||||
$window[callbackName] = function(data) {
|
||||
script.parentNode.removeChild(script)
|
||||
stream(data)
|
||||
stream(cast(args.type, data))
|
||||
if (typeof oncompletion === "function") oncompletion()
|
||||
delete $window[callbackName]
|
||||
}
|
||||
|
|
@ -125,5 +117,17 @@ module.exports = function($window) {
|
|||
|
||||
function extract(xhr) {return xhr.responseText}
|
||||
|
||||
function cast(type, data) {
|
||||
if (typeof type === "function") {
|
||||
if (data instanceof Array) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
data[i] = new type(data[i])
|
||||
}
|
||||
}
|
||||
else return new type(data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
return {xhr: xhr, jsonp: jsonp, setCompletionCallback: setCompletionCallback}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue